diff --git a/OpenBCI_GUI/Button.pde b/OpenBCI_GUI/Button.pde old mode 100755 new mode 100644 index 892d056..21c1505 --- a/OpenBCI_GUI/Button.pde +++ b/OpenBCI_GUI/Button.pde @@ -11,21 +11,24 @@ //////////////////// class Button { - + int but_x, but_y, but_dx, but_dy; // Position of square button //int rectSize = 90; // Diameter of rect - color color_pressed = color(200); + + color currentColor; + color color_hover = color(127, 134, 143);//color(252, 221, 198); + color color_pressed = color(227,118,37); //bgColor; color color_highlight = color(102); - color color_notPressed = color(255); + color color_notPressed = color(255); //color(227,118,37); color buttonStrokeColor = bgColor; color textColorActive = color(255); color textColorNotActive = bgColor; color rectHighlight; + boolean drawHand = false; //boolean isMouseHere = false; boolean buttonHasStroke = true; boolean isActive = false; boolean isDropdownButton = false; - boolean drawHand = false; boolean wasPressed = false; public String but_txt; PFont buttonFont = f2; @@ -46,54 +49,60 @@ class Button { but_dy = h; setString(txt); } - + public void setString(String txt) { but_txt = txt; //println("Button: setString: string = " + txt); } - + public boolean isActive() { return isActive; } - + public void setIsActive(boolean val) { isActive = val; } - public void makeDropdownButton(boolean val){ + public void makeDropdownButton(boolean val) { isDropdownButton = val; } - + public boolean isMouseHere() { if ( overRect(but_x, but_y, but_dx, but_dy) ) { - // cursor(HAND); + cursor(HAND); return true; - } - else { + } else { return false; } } color getColor() { if (isActive) { - return color_pressed; + currentColor = color_pressed; + } else if (isMouseHere()) { + currentColor = color_hover; } else { - return color_notPressed; + currentColor = color_notPressed; } + return currentColor; + } + + public void setCurrentColor(color _color){ + currentColor = _color; } - public void setColorPressed(color _color){ + public void setColorPressed(color _color) { color_pressed = _color; } - public void setColorNotPressed(color _color){ + public void setColorNotPressed(color _color) { color_notPressed = _color; } - public void setStrokeColor(color _color){ + public void setStrokeColor(color _color) { buttonStrokeColor = _color; } - public void hasStroke(boolean _trueORfalse){ + public void hasStroke(boolean _trueORfalse) { buttonHasStroke = _trueORfalse; } @@ -101,13 +110,12 @@ class Button { if (mouseX >= x && mouseX <= x+width && mouseY >= y && mouseY <= y+height) { return true; - } - else { + } else { return false; } } - public void draw(int _x, int _y){ + public void draw(int _x, int _y) { but_x = _x; but_y = _y; draw(); @@ -116,18 +124,18 @@ class Button { public void draw() { //draw the button fill(getColor()); - if(buttonHasStroke){ + if (buttonHasStroke) { stroke(buttonStrokeColor); //button border - }else{ + } else { noStroke(); } // noStroke(); - rect(but_x,but_y,but_dx,but_dy); - + rect(but_x, but_y, but_dx, but_dy); + //draw the text - if(isActive){ + if (isActive) { fill(textColorActive); - }else{ + } else { fill(textColorNotActive); } stroke(255); @@ -135,66 +143,54 @@ class Button { textSize(12); textAlign(CENTER, CENTER); textLeading(round(0.9*(textAscent()+textDescent()))); -// int x1 = but_x+but_dx/2; -// int y1 = but_y+but_dy/2; + // int x1 = but_x+but_dx/2; + // int y1 = but_y+but_dy/2; int x1, y1; - if (false) { - //auto wrap - x1 = but_x; - y1 = but_y; - int w = but_dx-2*2; //use a 2 pixel buffer on the left and right sides - int h = but_dy; - text(but_txt,x1,y1,w,h); - } else { - //no auto wrap - x1 = but_x+but_dx/2; - y1 = but_y+but_dy/2; - text(but_txt,x1,y1); - } + //no auto wrap + x1 = but_x+but_dx/2; + y1 = but_y+but_dy/2; + text(but_txt, x1, y1); //draw open/close arrow if it's a dropdown button - if(isDropdownButton){ + if (isDropdownButton) { pushStyle(); - fill(255); - noStroke(); - // smooth(); - // stroke(255); - // strokeWeight(1); - if(isActive){ - float point1x = but_x + (but_dx - ((3f*but_dy)/4f)); - float point1y = but_y + but_dy/3f; - float point2x = but_x + (but_dx-(but_dy/4f)); - float point2y = but_y + but_dy/3f; - float point3x = but_x + (but_dx - (but_dy/2f)); - float point3y = but_y + (2f*but_dy)/3f; - triangle(point1x, point1y, point2x, point2y, point3x, point3y); //downward triangle, indicating open - } else{ - float point1x = but_x + (but_dx - ((3f*but_dy)/4f)); - float point1y = but_y + (2f*but_dy)/3f; - float point2x = but_x + (but_dx-(but_dy/4f)); - float point2y = but_y + (2f*but_dy)/3f; - float point3x = but_x + (but_dx - (but_dy/2f)); - float point3y = but_y + but_dy/3f; - triangle(point1x, point1y, point2x, point2y, point3x, point3y); //upward triangle, indicating closed - } + fill(255); + noStroke(); + // smooth(); + // stroke(255); + // strokeWeight(1); + if (isActive) { + float point1x = but_x + (but_dx - ((3f*but_dy)/4f)); + float point1y = but_y + but_dy/3f; + float point2x = but_x + (but_dx-(but_dy/4f)); + float point2y = but_y + but_dy/3f; + float point3x = but_x + (but_dx - (but_dy/2f)); + float point3y = but_y + (2f*but_dy)/3f; + triangle(point1x, point1y, point2x, point2y, point3x, point3y); //downward triangle, indicating open + } else { + float point1x = but_x + (but_dx - ((3f*but_dy)/4f)); + float point1y = but_y + (2f*but_dy)/3f; + float point2x = but_x + (but_dx-(but_dy/4f)); + float point2y = but_y + (2f*but_dy)/3f; + float point3x = but_x + (but_dx - (but_dy/2f)); + float point3y = but_y + but_dy/3f; + triangle(point1x, point1y, point2x, point2y, point3x, point3y); //upward triangle, indicating closed + } popStyle(); } - if(systemMode == 0){ - if(!isMouseHere() && drawHand){ + if (true) { + if (!isMouseHere() && drawHand) { cursor(ARROW); drawHand = false; verbosePrint("don't draw hand"); } //if cursor is over button change cursor icon to hand! - if(isMouseHere() && !drawHand){ + if (isMouseHere() && !drawHand) { cursor(HAND); drawHand = true; verbosePrint("draw hand"); - } + } } } -}; - - - +}; \ No newline at end of file diff --git a/OpenBCI_GUI/ControlPanel.pde b/OpenBCI_GUI/ControlPanel.pde old mode 100755 new mode 100644 index 9f4ddd2..32cecab --- a/OpenBCI_GUI/ControlPanel.pde +++ b/OpenBCI_GUI/ControlPanel.pde @@ -35,7 +35,6 @@ String[] serialPorts = new String[Serial.list().length]; MenuList sdTimes; color boxColor = color(200); -// color boxStrokeColor = color(173,183,192); color boxStrokeColor = color(138, 146, 153); color isSelected_color = color(184, 220, 105); @@ -260,13 +259,13 @@ class ControlPanel { chanButton8.setIsActive(true); chanButton8Pressed = true; chanButton8.color_notPressed = isSelected_color; - chanButton16.color_notPressed = color(255); + chanButton16.color_notPressed = autoFileName.color_notPressed; //default color of button } if (chanButton16.isMouseHere()) { chanButton16.setIsActive(true); chanButton16Pressed = true; - chanButton8.color_notPressed = color(255); + chanButton8.color_notPressed = autoFileName.color_notPressed; //default color of button chanButton16.color_notPressed = isSelected_color; } } @@ -331,6 +330,7 @@ class ControlPanel { initSystemButton.setString("START SYSTEM"); haltSystem(); } + //cursor(ARROW); //this this back to ARROW } //open or close serial port if serial port button is pressed (left button in serial widget) @@ -401,10 +401,12 @@ public void controlEvent(ControlEvent theEvent) { if (theEvent.isFrom("sourceList")) { Map bob = ((MenuList)theEvent.getController()).getItem(int(theEvent.getValue())); - output("Data Source = " + (String)bob.get("headline")); + String str = (String)bob.get("headline"); + str = str.substring(0, str.length()-5); + //output("Data Source = " + str); int newDataSource = int(theEvent.getValue()); eegDataSource = newDataSource; // reset global eegDataSource to the selected value from the list - output("The new data source is " + (String)bob.get("headline")); + output("The new data source is " + str); } if (theEvent.isFrom("serialList")) { @@ -454,6 +456,7 @@ class DataSourceBox { } public void update() { + } public void draw() { @@ -758,8 +761,8 @@ class InitBox { //init button initSystemButton = new Button (padding, y + padding, w-padding*2, h - padding*2, "START SYSTEM", fontInfo.buttonLabel_size); - initSystemButton.color_notPressed = color(boxColor); - initSystemButton.buttonStrokeColor = color(boxColor); + //initSystemButton.color_notPressed = color(boolor); + //initSystemButton.buttonStrokeColor = color(boxColor); initButtonPressed = false; } @@ -769,7 +772,7 @@ class InitBox { public void draw() { pushStyle(); - fill(255); + fill(boxColor); stroke(boxStrokeColor); strokeWeight(1); rect(x, y, w, h); @@ -786,8 +789,4 @@ void playbackSelected(File selection) { output("You have selected \"" + selection.getAbsolutePath() + "\" for playback."); playbackData_fname = selection.getAbsolutePath(); } -} - - - - +} \ No newline at end of file diff --git a/OpenBCI_GUI/EEG_Processing.pde b/OpenBCI_GUI/EEG_Processing.pde index 944edc4..bcf35e9 100644 --- a/OpenBCI_GUI/EEG_Processing.pde +++ b/OpenBCI_GUI/EEG_Processing.pde @@ -1,6 +1,6 @@ //import ddf.minim.analysis.*; //for FFT -boolean drawUser = true; //if true... toggles on EEG_Processing_User.draw and toggles off the headplot in Gui_Manager +boolean drawUser = false; //if true... toggles on EEG_Processing_User.draw and toggles off the headplot in Gui_Manager class EEG_Processing_User { private float fs_Hz; //sample rate @@ -75,11 +75,11 @@ class EEG_Processing_User { //attempt to write to serial_output. If this serial port does not exist, do nothing. try { - println("inMoov_output: | " + output + " |"); + //println("inMoov_output: | " + output + " |"); serial_output.write(output); } catch(RuntimeException e){ - println("serial not present"); + if(isVerbose) println("serial not present"); } //OR, you could loop over each EEG channel and do some sort of frequency-domain processing from the FFT data @@ -129,8 +129,7 @@ class EEG_Processing_User { popStyle(); } - - myAverage = 0.0; + } class EEG_Processing { diff --git a/OpenBCI_GUI/MenuList.pde b/OpenBCI_GUI/MenuList.pde index 696c3fb..778a979 100644 --- a/OpenBCI_GUI/MenuList.pde +++ b/OpenBCI_GUI/MenuList.pde @@ -24,6 +24,7 @@ public class MenuList extends Controller { List< Map> items = new ArrayList< Map>(); PGraphics menu; boolean updateMenu; + boolean drawHand; int hoverItem = -1; int activeItem = -1; PFont menuFont = f2; @@ -45,6 +46,10 @@ public class MenuList extends Controller { updateMenu(); } if (inside()) { + if(!drawHand){ + cursor(HAND); + drawHand = true; + } menu.beginDraw(); int len = -(itemHeight * items.size()) + getHeight(); int ty; @@ -58,6 +63,12 @@ public class MenuList extends Controller { menu.rect(getWidth()-scrollerWidth-2, ty, scrollerWidth, scrollerLength ); } menu.endDraw(); + } + else { + if(drawHand){ + drawHand = false; + cursor(ARROW); + } } pg.image(menu, 0, 0); } diff --git a/OpenBCI_GUI/OpenBCI_GUI.pde b/OpenBCI_GUI/OpenBCI_GUI.pde index d18525f..fa60b27 100644 --- a/OpenBCI_GUI/OpenBCI_GUI.pde +++ b/OpenBCI_GUI/OpenBCI_GUI.pde @@ -67,8 +67,8 @@ int n_aux_ifEnabled = 3; // this is the accelerometer data CHIP 2014-11-03 //define variables related to warnings to the user about whether the EEG data is nearly railed (and, therefore, of dubious quality) DataStatus is_railed[]; -final int threshold_railed = int(pow(2,23)-1000); //fully railed should be +/- 2^23, so set this threshold close to that value -final int threshold_railed_warn = int(pow(2,23)*0.75); //set a somewhat smaller value as the warning threshold +final int threshold_railed = int(pow(2, 23)-1000); //fully railed should be +/- 2^23, so set this threshold close to that value +final int threshold_railed_warn = int(pow(2, 23)*0.75); //set a somewhat smaller value as the warning threshold //OpenBCI SD Card setting (if eegDataSource == 0) int sdSetting = 0; //0 = do not write; 1 = 5 min; 2 = 15 min; 3 = 30 min; etc... @@ -157,15 +157,18 @@ PFont f3; //========================SETUP============================// //========================SETUP============================// void setup() { - + println("Welcome to the Processing-based OpenBCI GUI!"); //Welcome line. + println("Last update: 2/16/2016"); //Welcome line. + println("For more information about how to work with this code base, please visit: http://docs.openbci.com/tutorials/01-GettingStarted"); + println("For specific questions, please post them to the Software section of the OpenBCI Forum: http://openbci.com/index.php/forum/#/categories/software"); //open window size(1024, 768, P2D); // size(displayWidth, displayHeight, P2D); //if (frame != null) frame.setResizable(true); //make window resizable //attach exit handler //prepareExitHandler(); - frameRate(16); - // smooth(); //turn this off if it's too slow + frameRate(30); //refresh rate ... this will slow automatically, if your processor can't handle the specified rate + smooth(); //turn this off if it's too slow surface.setResizable(true); //updated from frame.setResizable in Processing 2 @@ -176,13 +179,13 @@ void setup() { //listen for window resize ... used to adjust elements in application frame.addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { - if(e.getSource()==frame) { - println("OpenBCI_GUI: setup: RESIZED"); - screenHasBeenResized = true; - timeOfLastScreenResize = millis(); - // initializeGUI(); - } - } + if (e.getSource()==frame) { + println("OpenBCI_GUI: setup: RESIZED"); + screenHasBeenResized = true; + timeOfLastScreenResize = millis(); + // initializeGUI(); + } + } } ); @@ -197,8 +200,9 @@ void setup() { controlPanelCollapser.setIsActive(true); controlPanelCollapser.makeDropdownButton(true); - + //from the user's perspective, the program hangs out on the ControlPanel until the user presses "Start System". + print("Graphics & GUI Library: "); controlPanel = new ControlPanel(this); //The effect of "Start System" is that initSystem() gets called, which starts up the conneciton to the OpenBCI //hardware (via the "updateSyncState()" process) as well as initializing the rest of the GUI elements. @@ -207,7 +211,7 @@ void setup() { logo = loadImage("logo2.png"); playground = new Playground(navBarHeight); - + //attempt to open a serial port for "output" try { println("OpenBCI_GUI: attempting to open serial port for data output = " + serial_output_portName); @@ -217,7 +221,6 @@ void setup() { catch (RuntimeException e) { println("OpenBCI_GUI: *** ERROR ***: Could not open " + serial_output_portName); } - } //====================== END--OF ==========================// //========================SETUP============================// @@ -230,7 +233,7 @@ int byteRate_perSec = 0; int drawLoop_counter = 0; //used to init system based on initial settings...Called from the "Start System" button in the GUI's ControlPanel -void initSystem(){ +void initSystem() { verbosePrint("OpenBCI_GUI: initSystem: -- Init 0 --"); timeOfInit = millis(); //store this for timeout in case init takes too long @@ -243,17 +246,17 @@ void initSystem(){ //data_std_uV = new float[nchan]; data_elec_imp_ohm = new float[nchan]; is_railed = new DataStatus[nchan]; - for (int i=0; i= nPointsPerUpdate) { pointCounter = 0; //reset for next time - + //process the data processNewData(); - + //try to detect the desired signals, do it in frequency space...for OpenBCI_GUI_Simpler //detectInFreqDomain(fftBuff,inband_Hz,guard_Hz,detData_freqDomain); //gui.setDetectionData_freqDomain(detData_freqDomain); //tell the GUI that it has received new data via dumping new data into arrays that the GUI has pointers to - + // println("packet counter = " + newPacketCounter); // for(int i = 0; i < eegProcessing.data_std_uV.length; i++){ // println("eegProcessing.data_std_uV[" + i + "] = " + eegProcessing.data_std_uV[i]); // } - if((millis() - timeOfGUIreinitialize) > reinitializeGUIdelay){ //wait 1 second for GUI to reinitialize - try{ - gui.update(eegProcessing.data_std_uV,data_elec_imp_ohm); - } catch (Exception e){ + if ((millis() - timeOfGUIreinitialize) > reinitializeGUIdelay) { //wait 1 second for GUI to reinitialize + try { + gui.update(eegProcessing.data_std_uV, data_elec_imp_ohm); + } + catch (Exception e) { println(e.getMessage()); reinitializeGUIdelay = reinitializeGUIdelay * 2; println("OpenBCI_GUI: systemUpdate: New GUI reinitialize delay = " + reinitializeGUIdelay); } - } - else{ + } else { println("OpenBCI_GUI: systemUpdate: reinitializing GUI after resize... not updating GUI"); } - + ///add raw data to spectrogram...if the correct channel... //...look for the first channel that is active (meaning button is not active) or, if it // hasn't yet sent any data, send the last channel even if the channel is off - // if (sendToSpectrogram & (!(gui.chanButtons[Ichan].isActive()) | (Ichan == (nchan-1)))) { //send data to spectrogram - // sendToSpectrogram = false; //prevent us from sending more data after this time through - // for (int Idata=0;Idata < nPointsPerUpdate;Idata++) { - // gui.spectrogram.addDataPoint(yLittleBuff_uV[Ichan][Idata]); - // gui.tellGUIWhichChannelForSpectrogram(Ichan); - // //gui.spectrogram.addDataPoint(100.0f+(float)Idata); - // } - // } - + // if (sendToSpectrogram & (!(gui.chanButtons[Ichan].isActive()) | (Ichan == (nchan-1)))) { //send data to spectrogram + // sendToSpectrogram = false; //prevent us from sending more data after this time through + // for (int Idata=0;Idata < nPointsPerUpdate;Idata++) { + // gui.spectrogram.addDataPoint(yLittleBuff_uV[Ichan][Idata]); + // gui.tellGUIWhichChannelForSpectrogram(Ichan); + // //gui.spectrogram.addDataPoint(100.0f+(float)Idata); + // } + // } + redrawScreenNow=true; - } - else { + } else { //not enough data has arrived yet... only update the channel controller } } @@ -475,7 +482,7 @@ void systemUpdate(){ // for updating data values and variables updateButtons(); //make sure all system buttons are up to date //re-initialize GUI if screen has been resized and it's been more than 1/2 seccond (to prevent reinitialization of GUI from happening too often) - if(screenHasBeenResized == true && (millis() - timeOfLastScreenResize) > reinitializeGUIdelay){ + if (screenHasBeenResized == true && (millis() - timeOfLastScreenResize) > reinitializeGUIdelay) { screenHasBeenResized = false; println("systemUpdate: reinitializing GUI"); timeOfGUIreinitialize = millis(); @@ -489,78 +496,81 @@ void systemUpdate(){ // for updating data values and variables controlPanel.update(); } -void systemDraw(){ //for drawing to the screen - +void systemDraw() { //for drawing to the screen + //redraw the screen...not every time, get paced by when data is being plotted background(bgColor); //clear the screen - if(systemMode == 10){ + if (systemMode == 10) { int drawLoopCounter_thresh = 100; if ((redrawScreenNow) || (drawLoop_counter >= drawLoopCounter_thresh)) { //if (drawLoop_counter >= drawLoopCounter_thresh) println("OpenBCI_GUI: redrawing based on loop counter..."); drawLoop_counter=0; //reset for next time redrawScreenNow = false; //reset for next time - + //update the title of the figure; switch (eegDataSource) { - case DATASOURCE_NORMAL: case DATASOURCE_NORMAL_W_AUX: - surface.setTitle(int(frameRate) + " fps, Byte Count = " + openBCI_byteCount + ", bit rate = " + byteRate_perSec*8 + " bps" + ", " + int(float(fileoutput.getRowsWritten())/openBCI.get_fs_Hz()) + " secs Saved, Writing to " + output_fname); - break; - case DATASOURCE_SYNTHETIC: - surface.setTitle(int(frameRate) + " fps, Using Synthetic EEG Data"); - break; - case DATASOURCE_PLAYBACKFILE: - surface.setTitle(int(frameRate) + " fps, Playing " + int(float(currentTableRowIndex)/openBCI.get_fs_Hz()) + " of " + int(float(playbackData_table.getRowCount())/openBCI.get_fs_Hz()) + " secs, Reading from: " + playbackData_fname); - break; - } + case DATASOURCE_NORMAL: + case DATASOURCE_NORMAL_W_AUX: + surface.setTitle(int(frameRate) + " fps, Byte Count = " + openBCI_byteCount + ", bit rate = " + byteRate_perSec*8 + " bps" + ", " + int(float(fileoutput.getRowsWritten())/openBCI.get_fs_Hz()) + " secs Saved, Writing to " + output_fname); + break; + case DATASOURCE_SYNTHETIC: + surface.setTitle(int(frameRate) + " fps, Using Synthetic EEG Data"); + break; + case DATASOURCE_PLAYBACKFILE: + surface.setTitle(int(frameRate) + " fps, Playing " + int(float(currentTableRowIndex)/openBCI.get_fs_Hz()) + " of " + int(float(playbackData_table.getRowCount())/openBCI.get_fs_Hz()) + " secs, Reading from: " + playbackData_fname); + break; + } } //wait 1 second for GUI to reinitialize - if((millis() - timeOfGUIreinitialize) > reinitializeGUIdelay){ + if ((millis() - timeOfGUIreinitialize) > reinitializeGUIdelay) { // println("attempting to draw GUI..."); - try{ + try { // println("GUI DRAW!!! " + millis()); pushStyle(); - fill(255); - noStroke(); - rect(0, 0, width, navBarHeight); + fill(255); + noStroke(); + rect(0, 0, width, navBarHeight); popStyle(); gui.draw(); //draw the GUI // playground.draw(); - } catch (Exception e){ + } + catch (Exception e) { println(e.getMessage()); reinitializeGUIdelay = reinitializeGUIdelay * 2; println("OpenBCI_GUI: systemDraw: New GUI reinitialize delay = " + reinitializeGUIdelay); } - } - else{ + } else { //reinitializing GUI after resize println("OpenBCI_GUI: systemDraw: reinitializing GUI after resize... not drawing GUI"); } playground.draw(); - if(drawUser){ + if (drawUser) { eegProcessing_user.draw(); } - + } else { //systemMode != 10 + //still print title information about fps + surface.setTitle(int(frameRate) + " fps — OpenBCI GUI"); } //control panel - if(controlPanel.isOpen){ + if (controlPanel.isOpen) { controlPanel.draw(); } controlPanelCollapser.draw(); helpWidget.draw(); - if((openBCI.get_state() == openBCI.STATE_COMINIT || openBCI.get_state() == openBCI.STATE_SYNCWITHHARDWARE) && systemMode == 0){ + if ((openBCI.get_state() == openBCI.STATE_COMINIT || openBCI.get_state() == openBCI.STATE_SYNCWITHHARDWARE) && systemMode == 0) { //make out blink the text "Initalizing GUI..." - if(millis()%1000 < 500){ + if (millis()%1000 < 500) { output("Iniitializing communication w/ your OpenBCI board..."); - } else{ + } else { output(""); } - if(millis() - timeOfInit > 12000){ + if (millis() - timeOfInit > 12000) { haltSystem(); initSystemButton.but_txt = "START SYSTEM"; output("Init timeout. Verify your Serial/COM Port. Power DOWN/UP your OpenBCI & USB Dongle. Then retry Initialization."); @@ -570,29 +580,33 @@ void systemDraw(){ //for drawing to the screen // use commented code below to verify frameRate and check latency // println("Time since start: " + millis() + " || Time since last frame: " + str(millis()-timeOfLastFrame)); // timeOfLastFrame = millis(); + + //if(!drawHand) { + // cursor(ARROW); + //} } //called from systemUpdate when mode=10 and isRunning = true int getDataIfAvailable(int pointCounter) { - + if ( (eegDataSource == DATASOURCE_NORMAL) || (eegDataSource == DATASOURCE_NORMAL_W_AUX) ) { //get data from serial port as it streams in - //first, get the new data (if any is available) - // openBCI.finalizeCOMINIT(); //this is trying to listen to the openBCI hardware. New data is put into dataPacketBuff and increments curDataPacketInd. - - //next, gather any new data into the "little buffer" - while ( (curDataPacketInd != lastReadDataPacketInd) && (pointCounter < nPointsPerUpdate)) { - lastReadDataPacketInd = (lastReadDataPacketInd+1) % dataPacketBuff.length; //increment to read the next packet - for (int Ichan=0; Ichan < nchan; Ichan++) { //loop over each cahnnel - //scale the data into engineering units ("microvolts") and save to the "little buffer" - yLittleBuff_uV[Ichan][pointCounter] = dataPacketBuff[lastReadDataPacketInd].values[Ichan] * openBCI.get_scale_fac_uVolts_per_count(); - } - pointCounter++; //increment counter for "little buffer" - } + //first, get the new data (if any is available) + // openBCI.finalizeCOMINIT(); //this is trying to listen to the openBCI hardware. New data is put into dataPacketBuff and increments curDataPacketInd. + + //next, gather any new data into the "little buffer" + while ( (curDataPacketInd != lastReadDataPacketInd) && (pointCounter < nPointsPerUpdate)) { + lastReadDataPacketInd = (lastReadDataPacketInd+1) % dataPacketBuff.length; //increment to read the next packet + for (int Ichan=0; Ichan < nchan; Ichan++) { //loop over each cahnnel + //scale the data into engineering units ("microvolts") and save to the "little buffer" + yLittleBuff_uV[Ichan][pointCounter] = dataPacketBuff[lastReadDataPacketInd].values[Ichan] * openBCI.get_scale_fac_uVolts_per_count(); + } + pointCounter++; //increment counter for "little buffer" + } } else { // make or load data to simulate real time - + //has enough time passed? int current_millis = millis(); if (current_millis >= nextPlayback_millis) { @@ -607,14 +621,14 @@ int getDataIfAvailable(int pointCounter) { // println(); dataPacketBuff[lastReadDataPacketInd].sampleIndex++; switch (eegDataSource) { - case DATASOURCE_SYNTHETIC: //use synthetic data (for GUI debugging) - synthesizeData(nchan, openBCI.get_fs_Hz(), openBCI.get_scale_fac_uVolts_per_count(), dataPacketBuff[lastReadDataPacketInd]); - break; - case DATASOURCE_PLAYBACKFILE: - currentTableRowIndex=getPlaybackDataFromTable(playbackData_table,currentTableRowIndex,openBCI.get_scale_fac_uVolts_per_count(), dataPacketBuff[lastReadDataPacketInd]); - break; - default: - //no action + case DATASOURCE_SYNTHETIC: //use synthetic data (for GUI debugging) + synthesizeData(nchan, openBCI.get_fs_Hz(), openBCI.get_scale_fac_uVolts_per_count(), dataPacketBuff[lastReadDataPacketInd]); + break; + case DATASOURCE_PLAYBACKFILE: + currentTableRowIndex=getPlaybackDataFromTable(playbackData_table, currentTableRowIndex, openBCI.get_scale_fac_uVolts_per_count(), dataPacketBuff[lastReadDataPacketInd]); + break; + default: + //no action } //gather the data into the "little buffer" for (int Ichan=0; Ichan < nchan; Ichan++) { @@ -641,7 +655,7 @@ void processNewData() { prevMillis=millis(); //store for next time prevBytes = openBCI_byteCount; //store for next time - + //compute smoothed byte rate avgBitRate.addValue(inst_byteRate_perSec); byteRate_perSec = (int)avgBitRate.calcMean(); @@ -652,91 +666,92 @@ void processNewData() { double foo; //update the data buffers - for (int Ichan=0;Ichan < nchan; Ichan++) { + for (int Ichan=0; Ichan < nchan; Ichan++) { //append the new data to the larger data buffer...because we want the plotting routines //to show more than just the most recent chunk of data. This will be our "raw" data. appendAndShift(dataBuffY_uV[Ichan], yLittleBuff_uV[Ichan]); - + //make a copy of the data that we'll apply processing to. This will be what is displayed on the full montage dataBuffY_filtY_uV[Ichan] = dataBuffY_uV[Ichan].clone(); } - + //if you want to, re-reference the montage to make it be a mean-head reference if (false) rereferenceTheMontage(dataBuffY_filtY_uV); - + //update the FFT (frequency spectrum) - for (int Ichan=0;Ichan < nchan; Ichan++) { + for (int Ichan=0; Ichan < nchan; Ichan++) { //copy the previous FFT data...enables us to apply some smoothing to the FFT data for (int I=0; I < fftBuff[Ichan].specSize(); I++) prevFFTdata[I] = fftBuff[Ichan].getBand(I); //copy the old spectrum values - + //prepare the data for the new FFT float[] fooData_raw = dataBuffY_uV[Ichan]; //use the raw data for the FFT fooData_raw = Arrays.copyOfRange(fooData_raw, fooData_raw.length-Nfft, fooData_raw.length); //trim to grab just the most recent block of data float meanData = mean(fooData_raw); //compute the mean for (int I=0; I < fooData_raw.length; I++) fooData_raw[I] -= meanData; //remove the mean (for a better looking FFT - + //compute the FFT fftBuff[Ichan].forward(fooData_raw); //compute FFT on this channel of data - - - -// //convert units on fft data -// if (false) { -// //convert units to uV_per_sqrtHz...is this still correct?? CHIP 2014-10-24 -// //final float mean_winpow_sqr = 0.3966; //account for power lost when windowing...mean(hamming(N).^2) = 0.3966 -// final float mean_winpow = 1.0f/sqrt(2.0f); //account for power lost when windowing...mean(hamming(N).^2) = 0.3966 -// final float scale_raw_to_rtHz = pow((float)fftBuff[0].specSize(),1)*fs_Hz*mean_winpow; //normalize the amplitude by the number of bins to get the correct scaling to uV/sqrt(Hz)??? -// double foo; -// for (int I=0; I < fftBuff[Ichan].specSize(); I++) { //loop over each FFT bin -// foo = sqrt(pow(fftBuff[Ichan].getBand(I),2)/scale_raw_to_rtHz); -// fftBuff[Ichan].setBand(I,(float)foo); -// //if ((Ichan==0) & (I > 5) & (I < 15)) println("processFreqDomain: uV/rtHz = " + I + " " + foo); -// } -// } else { - //convert to uV_per_bin...still need to confirm the accuracy of this code. - //Do we need to account for the power lost in the windowing function? CHIP 2014-10-24 - for (int I=0; I < fftBuff[Ichan].specSize(); I++) { //loop over each FFT bin - fftBuff[Ichan].setBand(I,(float)(fftBuff[Ichan].getBand(I) / fftBuff[Ichan].specSize())); - } -// } - + + + + // //convert units on fft data + // if (false) { + // //convert units to uV_per_sqrtHz...is this still correct?? CHIP 2014-10-24 + // //final float mean_winpow_sqr = 0.3966; //account for power lost when windowing...mean(hamming(N).^2) = 0.3966 + // final float mean_winpow = 1.0f/sqrt(2.0f); //account for power lost when windowing...mean(hamming(N).^2) = 0.3966 + // final float scale_raw_to_rtHz = pow((float)fftBuff[0].specSize(),1)*fs_Hz*mean_winpow; //normalize the amplitude by the number of bins to get the correct scaling to uV/sqrt(Hz)??? + // double foo; + // for (int I=0; I < fftBuff[Ichan].specSize(); I++) { //loop over each FFT bin + // foo = sqrt(pow(fftBuff[Ichan].getBand(I),2)/scale_raw_to_rtHz); + // fftBuff[Ichan].setBand(I,(float)foo); + // //if ((Ichan==0) & (I > 5) & (I < 15)) println("processFreqDomain: uV/rtHz = " + I + " " + foo); + // } + // } else { + //convert to uV_per_bin...still need to confirm the accuracy of this code. + //Do we need to account for the power lost in the windowing function? CHIP 2014-10-24 + for (int I=0; I < fftBuff[Ichan].specSize(); I++) { //loop over each FFT bin + fftBuff[Ichan].setBand(I, (float)(fftBuff[Ichan].getBand(I) / fftBuff[Ichan].specSize())); + } + // } + //average the FFT with previous FFT data so that it makes it smoother in time double min_val = 0.01d; for (int I=0; I < fftBuff[Ichan].specSize(); I++) { //loop over each fft bin if (prevFFTdata[I] < min_val) prevFFTdata[I] = (float)min_val; //make sure we're not too small for the log calls - foo = fftBuff[Ichan].getBand(I); if (foo < min_val) foo = min_val; //make sure this value isn't too small - - if (true) { + foo = fftBuff[Ichan].getBand(I); + if (foo < min_val) foo = min_val; //make sure this value isn't too small + + if (true) { //smooth in dB power space - foo = (1.0d-smoothFac[smoothFac_ind]) * java.lang.Math.log(java.lang.Math.pow(foo,2)); - foo += smoothFac[smoothFac_ind] * java.lang.Math.log(java.lang.Math.pow((double)prevFFTdata[I],2)); + foo = (1.0d-smoothFac[smoothFac_ind]) * java.lang.Math.log(java.lang.Math.pow(foo, 2)); + foo += smoothFac[smoothFac_ind] * java.lang.Math.log(java.lang.Math.pow((double)prevFFTdata[I], 2)); foo = java.lang.Math.sqrt(java.lang.Math.exp(foo)); //average in dB space } else { //smooth (average) in linear power space - foo = (1.0d-smoothFac[smoothFac_ind]) * java.lang.Math.pow(foo,2); - foo+= smoothFac[smoothFac_ind] * java.lang.Math.pow((double)prevFFTdata[I],2); + foo = (1.0d-smoothFac[smoothFac_ind]) * java.lang.Math.pow(foo, 2); + foo+= smoothFac[smoothFac_ind] * java.lang.Math.pow((double)prevFFTdata[I], 2); // take sqrt to be back into uV_rtHz foo = java.lang.Math.sqrt(foo); } - fftBuff[Ichan].setBand(I,(float)foo); //put the smoothed data back into the fftBuff data holder for use by everyone else + fftBuff[Ichan].setBand(I, (float)foo); //put the smoothed data back into the fftBuff data holder for use by everyone else } //end loop over FFT bins } //end the loop over channels. - + //apply additional processing for the time-domain montage plot (ie, filtering) - eegProcessing.process(yLittleBuff_uV,dataBuffY_uV,dataBuffY_filtY_uV,fftBuff); - + eegProcessing.process(yLittleBuff_uV, dataBuffY_uV, dataBuffY_filtY_uV, fftBuff); + //apply user processing // ...yLittleBuff_uV[Ichan] is the most recent raw data since the last call to this processing routine // ...dataBuffY_filtY_uV[Ichan] is the full set of filtered data as shown in the time-domain plot in the GUI // ...fftBuff[Ichan] is the FFT data structure holding the frequency spectrum as shown in the freq-domain plot in the GUI - eegProcessing_user.process(yLittleBuff_uV,dataBuffY_uV,dataBuffY_filtY_uV,fftBuff); - + eegProcessing_user.process(yLittleBuff_uV, dataBuffY_uV, dataBuffY_filtY_uV, fftBuff); + //look to see if the latest data is railed so that we can notify the user on the GUI - for (int Ichan=0;Ichan < nchan; Ichan++) is_railed[Ichan].update(dataPacketBuff[lastReadDataPacketInd].values[Ichan]); + for (int Ichan=0; Ichan < nchan; Ichan++) is_railed[Ichan].update(dataPacketBuff[lastReadDataPacketInd].values[Ichan]); //compute the electrode impedance. Do it in a very simple way [rms to amplitude, then uVolt to Volt, then Volt/Amp to Ohm] - for (int Ichan=0;Ichan < nchan; Ichan++) data_elec_imp_ohm[Ichan] = (sqrt(2.0)*eegProcessing.data_std_uV[Ichan]*1.0e-6) / openBCI.get_leadOffDrive_amps(); + for (int Ichan=0; Ichan < nchan; Ichan++) data_elec_imp_ohm[Ichan] = (sqrt(2.0)*eegProcessing.data_std_uV[Ichan]*1.0e-6) / openBCI.get_leadOffDrive_amps(); } //helper function in handling the EEG data @@ -746,7 +761,7 @@ void appendAndShift(float[] data, float[] newData) { for (int i=0; i < end; i++) { data[i]=data[i+nshift]; //shift data points down by 1 } - for (int i=0; i= 10){ + if (systemMode >= 10) { //limit interactivity of main GUI if control panel is open - if(controlPanel.isOpen == false){ + if (controlPanel.isOpen == false) { //was the stopButton pressed? gui.mousePressed(); // trigger mousePressed function in GUI @@ -826,9 +840,9 @@ void mousePressed() { if (gui.stopButton.isMouseHere()) { gui.stopButton.setIsActive(true); - stopButtonWasPressed(); + stopButtonWasPressed(); } - + // //was the gui page button pressed? // if (gui.guiPageButton.isMouseHere()) { // gui.guiPageButton.setIsActive(true); @@ -837,98 +851,94 @@ void mousePressed() { //check the buttons switch (gui.guiPage) { - case Gui_Manager.GUI_PAGE_CHANNEL_ONOFF: - //check the channel buttons - // for (int Ibut = 0; Ibut < gui.chanButtons.length; Ibut++) { - // if (gui.chanButtons[Ibut].isMouseHere()) { - // toggleChannelState(Ibut); - // } - // } - - //check the detection button - //if (gui.detectButton.updateIsMouseHere()) toggleDetectionState(); - //check spectrogram button - //if (gui.spectrogramButton.updateIsMouseHere()) toggleSpectrogramState(); - - break; - case Gui_Manager.GUI_PAGE_IMPEDANCE_CHECK: - // ============ DEPRECATED ============== // - // //check the impedance buttons - // for (int Ibut = 0; Ibut < gui.impedanceButtonsP.length; Ibut++) { - // if (gui.impedanceButtonsP[Ibut].isMouseHere()) { - // toggleChannelImpedanceState(gui.impedanceButtonsP[Ibut],Ibut,0); - // } - // if (gui.impedanceButtonsN[Ibut].isMouseHere()) { - // toggleChannelImpedanceState(gui.impedanceButtonsN[Ibut],Ibut,1); - // } - // } - // if (gui.biasButton.isMouseHere()) { - // gui.biasButton.setIsActive(true); - // setBiasState(!openBCI.isBiasAuto); - // } - // break; - case Gui_Manager.GUI_PAGE_HEADPLOT_SETUP: - if (gui.intensityFactorButton.isMouseHere()) { - gui.intensityFactorButton.setIsActive(true); - gui.incrementVertScaleFactor(); - } - if (gui.loglinPlotButton.isMouseHere()) { - gui.loglinPlotButton.setIsActive(true); - gui.set_vertScaleAsLog(!gui.vertScaleAsLog); //toggle the state - } - if (gui.filtBPButton.isMouseHere()) { - gui.filtBPButton.setIsActive(true); - incrementFilterConfiguration(); - } - if (gui.filtNotchButton.isMouseHere()) { - gui.filtNotchButton.setIsActive(true); - incrementNotchConfiguration(); - } - if (gui.smoothingButton.isMouseHere()) { - gui.smoothingButton.setIsActive(true); - incrementSmoothing(); - } - if (gui.showPolarityButton.isMouseHere()) { - gui.showPolarityButton.setIsActive(true); - toggleShowPolarity(); - } - if (gui.maxDisplayFreqButton.isMouseHere()) { - gui.maxDisplayFreqButton.setIsActive(true); - gui.incrementMaxDisplayFreq(); - } - - // //check the detection button - // if (gui.detectButton.updateIsMouseHere()) { - // gui.detectButton.setIsActive(true); - // toggleDetectionState(); - // } - // //check spectrogram button - // if (gui.spectrogramButton.updateIsMouseHere()) { - // gui.spectrogramButton.setIsActive(true); - // toggleSpectrogramState(); - // } + case Gui_Manager.GUI_PAGE_CHANNEL_ONOFF: + //check the channel buttons + // for (int Ibut = 0; Ibut < gui.chanButtons.length; Ibut++) { + // if (gui.chanButtons[Ibut].isMouseHere()) { + // toggleChannelState(Ibut); + // } + // } - break; + //check the detection button + //if (gui.detectButton.updateIsMouseHere()) toggleDetectionState(); + //check spectrogram button + //if (gui.spectrogramButton.updateIsMouseHere()) toggleSpectrogramState(); + + break; + case Gui_Manager.GUI_PAGE_IMPEDANCE_CHECK: + // ============ DEPRECATED ============== // + // //check the impedance buttons + // for (int Ibut = 0; Ibut < gui.impedanceButtonsP.length; Ibut++) { + // if (gui.impedanceButtonsP[Ibut].isMouseHere()) { + // toggleChannelImpedanceState(gui.impedanceButtonsP[Ibut],Ibut,0); + // } + // if (gui.impedanceButtonsN[Ibut].isMouseHere()) { + // toggleChannelImpedanceState(gui.impedanceButtonsN[Ibut],Ibut,1); + // } + // } + // if (gui.biasButton.isMouseHere()) { + // gui.biasButton.setIsActive(true); + // setBiasState(!openBCI.isBiasAuto); + // } + // break; + case Gui_Manager.GUI_PAGE_HEADPLOT_SETUP: + if (gui.intensityFactorButton.isMouseHere()) { + gui.intensityFactorButton.setIsActive(true); + gui.incrementVertScaleFactor(); + } + if (gui.loglinPlotButton.isMouseHere()) { + gui.loglinPlotButton.setIsActive(true); + gui.set_vertScaleAsLog(!gui.vertScaleAsLog); //toggle the state + } + if (gui.filtBPButton.isMouseHere()) { + gui.filtBPButton.setIsActive(true); + incrementFilterConfiguration(); + } + if (gui.filtNotchButton.isMouseHere()) { + gui.filtNotchButton.setIsActive(true); + incrementNotchConfiguration(); + } + if (gui.smoothingButton.isMouseHere()) { + gui.smoothingButton.setIsActive(true); + incrementSmoothing(); + } + if (gui.showPolarityButton.isMouseHere()) { + gui.showPolarityButton.setIsActive(true); + toggleShowPolarity(); + } + if (gui.maxDisplayFreqButton.isMouseHere()) { + gui.maxDisplayFreqButton.setIsActive(true); + gui.incrementMaxDisplayFreq(); + } + + // //check the detection button + // if (gui.detectButton.updateIsMouseHere()) { + // gui.detectButton.setIsActive(true); + // toggleDetectionState(); + // } + // //check spectrogram button + // if (gui.spectrogramButton.updateIsMouseHere()) { + // gui.spectrogramButton.setIsActive(true); + // toggleSpectrogramState(); + // } + + break; //default: } - + //check the graphs - if (gui.isMouseOnFFT(mouseX,mouseY)) { + if (gui.isMouseOnFFT(mouseX, mouseY)) { GraphDataPoint dataPoint = new GraphDataPoint(); - gui.getFFTdataPoint(mouseX,mouseY,dataPoint); - println("OpenBCI_GUI: FFT data point: " + String.format("%4.2f",dataPoint.x) + " " + dataPoint.x_units + ", " + String.format("%4.2f",dataPoint.y) + " " + dataPoint.y_units); - } else if (gui.headPlot1.isPixelInsideHead(mouseX,mouseY)) { + gui.getFFTdataPoint(mouseX, mouseY, dataPoint); + println("OpenBCI_GUI: FFT data point: " + String.format("%4.2f", dataPoint.x) + " " + dataPoint.x_units + ", " + String.format("%4.2f", dataPoint.y) + " " + dataPoint.y_units); + } else if (gui.headPlot1.isPixelInsideHead(mouseX, mouseY)) { //toggle the head plot contours gui.headPlot1.drawHeadAsContours = !gui.headPlot1.drawHeadAsContours; - } else if (gui.isMouseOnMontage(mouseX,mouseY)) { + } else if (gui.isMouseOnMontage(mouseX, mouseY)) { //toggle the display of the montage values gui.showMontageValues = !gui.showMontageValues; } - - } - - } //=============================// @@ -937,30 +947,29 @@ void mousePressed() { //was control panel button pushed if (controlPanelCollapser.isMouseHere()) { - if(controlPanelCollapser.isActive && systemMode == 10){ + if (controlPanelCollapser.isActive && systemMode == 10) { controlPanelCollapser.setIsActive(false); controlPanel.isOpen = false; - } - else{ + } else { controlPanelCollapser.setIsActive(true); controlPanel.isOpen = true; } - } else{ - if(controlPanel.isOpen){ + } else { + if (controlPanel.isOpen) { controlPanel.CPmousePressed(); } } //interacting with control panel - if(controlPanel.isOpen){ + if (controlPanel.isOpen) { //close control panel if you click outside... - if(systemMode == 10){ - if(mouseX > 0 && mouseX < controlPanel.w && mouseY > 0 && mouseY < controlPanel.initBox.y+controlPanel.initBox.h){ + if (systemMode == 10) { + if (mouseX > 0 && mouseX < controlPanel.w && mouseY > 0 && mouseY < controlPanel.initBox.y+controlPanel.initBox.h) { println("OpenBCI_GUI: mousePressed: clicked in CP box"); controlPanel.CPmousePressed(); } //if clicked out of panel - else{ + else { println("OpenBCI_GUI: mousePressed: outside of CP clicked"); controlPanel.isOpen = false; controlPanelCollapser.setIsActive(false); @@ -971,11 +980,11 @@ void mousePressed() { redrawScreenNow = true; //command a redraw of the GUI whenever the mouse is pressed - if(playground.isMouseHere()){ + if (playground.isMouseHere()) { playground.mousePressed(); } - if(playground.isMouseInButton()){ + if (playground.isMouseInButton()) { playground.toggleWindow(); } } @@ -988,57 +997,57 @@ void mouseReleased() { //released the mouse button, turn off those buttons. //interacting with control panel - if(controlPanel.isOpen){ + if (controlPanel.isOpen) { //if clicked in panel controlPanel.CPmouseReleased(); } - if(systemMode >= 10){ + if (systemMode >= 10) { gui.mouseReleased(); redrawScreenNow = true; //command a redraw of the GUI whenever the mouse is released } - if(screenHasBeenResized){ + if (screenHasBeenResized) { println("OpenBCI_GUI: mouseReleased: screen has been resized..."); screenHasBeenResized = false; } //Playground Interactivity - if(playground.isMouseHere()){ + if (playground.isMouseHere()) { playground.mouseReleased(); } - if(playground.isMouseInButton()){ + if (playground.isMouseInButton()) { // playground.toggleWindow(); } } -void printRegisters(){ +void printRegisters() { openBCI.printRegisters(); // printingRegisters = true; } void stopRunning() { - // openBCI.changeState(0); //make sure it's no longer interpretting as binary - verbosePrint("OpenBCI_GUI: stopRunning: stop running..."); - output("Data stream stopped."); - if (openBCI != null) { - openBCI.stopDataTransfer(); - } - timeSinceStopRunning = millis(); //used as a timer to prevent misc. bytes from flooding serial... - isRunning = false; - // openBCI.changeState(0); //make sure it's no longer interpretting as binary - // systemMode = 0; - // closeLogFile(); + // openBCI.changeState(0); //make sure it's no longer interpretting as binary + verbosePrint("OpenBCI_GUI: stopRunning: stop running..."); + output("Data stream stopped."); + if (openBCI != null) { + openBCI.stopDataTransfer(); + } + timeSinceStopRunning = millis(); //used as a timer to prevent misc. bytes from flooding serial... + isRunning = false; + // openBCI.changeState(0); //make sure it's no longer interpretting as binary + // systemMode = 0; + // closeLogFile(); } void startRunning() { - verbosePrint("startRunning..."); - output("Data stream started."); - if ((eegDataSource == DATASOURCE_NORMAL) || (eegDataSource == DATASOURCE_NORMAL_W_AUX)) { - if (openBCI != null) openBCI.startDataTransfer(); - } - isRunning = true; + verbosePrint("startRunning..."); + output("Data stream started."); + if ((eegDataSource == DATASOURCE_NORMAL) || (eegDataSource == DATASOURCE_NORMAL_W_AUX)) { + if (openBCI != null) openBCI.startDataTransfer(); + } + isRunning = true; } //execute this function whenver the stop button is pressed @@ -1047,26 +1056,24 @@ void stopButtonWasPressed() { if (isRunning) { println("openBCI_GUI: stopButton was pressed...stopping data transfer..."); stopRunning(); - } - else { //not running + } else { //not running println("openBCI_GUI: startButton was pressed...starting data transfer..."); startRunning(); nextPlayback_millis = millis(); //used for synthesizeData and readFromFile. This restarts the clock that keeps the playback at the right pace. } } -void updateButtons(){ +void updateButtons() { //update the stop button with new text based on the current running state //gui.stopButton.setActive(isRunning); if (isRunning) { //println("OpenBCI_GUI: stopButtonWasPressed (a): changing string to " + Gui_Manager.stopButton_pressToStop_txt); gui.stopButton.setString(Gui_Manager.stopButton_pressToStop_txt); gui.stopButton.setColorNotPressed(color(224, 56, 45)); - } - else { + } else { //println("OpenBCI_GUI: stopButtonWasPressed (a): changing string to " + Gui_Manager.stopButton_pressToStart_txt); gui.stopButton.setString(Gui_Manager.stopButton_pressToStart_txt); - gui.stopButton.setColorNotPressed(color(184,220,105)); + gui.stopButton.setColorNotPressed(color(184, 220, 105)); } } @@ -1079,7 +1086,7 @@ void synthesizeData(int nchan, float fs_Hz, float scale_fac_uVolts_per_count, Da val_uV = randomGaussian()*sqrt(fs_Hz/2.0f); // ensures that it has amplitude of one unit per sqrt(Hz) of signal bandwidth //val_uV = random(1)*sqrt(fs_Hz/2.0f); // ensures that it has amplitude of one unit per sqrt(Hz) of signal bandwidth if (Ichan==0) val_uV*= 10f; //scale one channel higher - + if (Ichan==1) { //add sine wave at 10 Hz at 10 uVrms sine_phase_rad[Ichan] += 2.0f*PI * sine_freq_Hz / fs_Hz; @@ -1094,7 +1101,7 @@ void synthesizeData(int nchan, float fs_Hz, float scale_fac_uVolts_per_count, Da //60 Hz interference at 50 uVrms sine_phase_rad[Ichan] += 2.0f*PI * 60.0f / fs_Hz; //50 Hz if (sine_phase_rad[Ichan] > 2.0f*PI) sine_phase_rad[Ichan] -= 2.0f*PI; - val_uV += 50.0f * sqrt(2.0)*sin(sine_phase_rad[Ichan]); //20 uVrms + val_uV += 50.0f * sqrt(2.0)*sin(sine_phase_rad[Ichan]); //20 uVrms } } else { val_uV = 0.0f; @@ -1105,7 +1112,7 @@ void synthesizeData(int nchan, float fs_Hz, float scale_fac_uVolts_per_count, Da int getPlaybackDataFromTable(Table datatable, int currentTableRowIndex, float scale_fac_uVolts_per_count, DataPacket_ADS1299 curDataPacket) { float val_uV = 0.0f; - + //check to see if we can load a value from the table if (currentTableRowIndex >= datatable.getRowCount()) { //end of file @@ -1116,7 +1123,7 @@ int getPlaybackDataFromTable(Table datatable, int currentTableRowIndex, float sc //get the row TableRow row = datatable.getRow(currentTableRowIndex); currentTableRowIndex++; //increment to the next row - + //get each value for (int Ichan=0; Ichan < nchan; Ichan++) { if (isChannelActive(Ichan) && (Ichan < datatable.getColumnCount())) { @@ -1148,9 +1155,9 @@ int getPlaybackDataFromTable(Table datatable, int currentTableRowIndex, float sc //Ichan is zero referenced (not one referenced) boolean isChannelActive(int Ichan) { boolean return_val = false; - if(channelSettingValues[Ichan][0] == '1'){ + if (channelSettingValues[Ichan][0] == '1') { return_val = false; - } else{ + } else { return_val = true; } return return_val; @@ -1159,20 +1166,20 @@ boolean isChannelActive(int Ichan) { //activateChannel: Ichan is [0 nchan-1] (aka zero referenced) void activateChannel(int Ichan) { println("OpenBCI_GUI: activating channel " + (Ichan+1)); - if(eegDataSource == DATASOURCE_NORMAL || eegDataSource == DATASOURCE_NORMAL_W_AUX){ - if (openBCI.isSerialPortOpen()){ + if (eegDataSource == DATASOURCE_NORMAL || eegDataSource == DATASOURCE_NORMAL_W_AUX) { + if (openBCI.isSerialPortOpen()) { verbosePrint("**"); openBCI.changeChannelState(Ichan, true); //activate } } - if (Ichan < gui.chanButtons.length){ + if (Ichan < gui.chanButtons.length) { channelSettingValues[Ichan][0] = '0'; gui.cc.update(); } } void deactivateChannel(int Ichan) { println("OpenBCI_GUI: deactivating channel " + (Ichan+1)); - if(eegDataSource == DATASOURCE_NORMAL || eegDataSource == DATASOURCE_NORMAL_W_AUX){ + if (eegDataSource == DATASOURCE_NORMAL || eegDataSource == DATASOURCE_NORMAL_W_AUX) { if (openBCI.isSerialPortOpen()) { verbosePrint("**"); openBCI.changeChannelState(Ichan, false); //de-activate @@ -1216,7 +1223,7 @@ void deactivateChannel(int Ichan) { // if ((Ichan >= 0) && (Ichan < gui.impedanceButtonsP.length)) { // //change the state of the OpenBCI channel itself // if (openBCI != null) openBCI.changeImpedanceState(Ichan,newstate,code_P_N_Both); - + // //now update the button state // if ((code_P_N_Both == 0) || (code_P_N_Both == 2)) { // //set the P channel @@ -1232,10 +1239,10 @@ void deactivateChannel(int Ichan) { //=========== DEPRECATED w/ CHANNEL CONTROLLER ===========// // void setBiasState(boolean state) { // openBCI.isBiasAuto = state; - + // //send message to openBCI // if (openBCI != null) openBCI.setBiasAutoState(state); - + // //change button text // if (openBCI.isBiasAuto) { // gui.biasButton.but_txt = "Bias\nAuto"; @@ -1250,7 +1257,7 @@ void openNewLogFile(String _fileName) { println("OpenBCI_GUI: closing log file"); closeLogFile(); } - + //open the new file fileoutput = new OutputFile_rawtxt(openBCI.get_fs_Hz(), _fileName); output_fname = fileoutput.fname; @@ -1264,34 +1271,34 @@ void closeLogFile() { void incrementFilterConfiguration() { eegProcessing.incrementFilterConfiguration(); - + //update the button strings gui.filtBPButton.but_txt = "BP Filt\n" + eegProcessing.getShortFilterDescription(); - gui.titleMontage.string = "EEG Data (" + eegProcessing.getFilterDescription() + ")"; + gui.titleMontage.string = "EEG Data (" + eegProcessing.getFilterDescription() + ")"; } void incrementNotchConfiguration() { eegProcessing.incrementNotchConfiguration(); - + //update the button strings gui.filtNotchButton.but_txt = "Notch\n" + eegProcessing.getShortNotchDescription(); - gui.titleMontage.string = "EEG Data (" + eegProcessing.getFilterDescription() + ")"; + gui.titleMontage.string = "EEG Data (" + eegProcessing.getFilterDescription() + ")"; } - + void incrementSmoothing() { smoothFac_ind++; if (smoothFac_ind >= smoothFac.length) smoothFac_ind = 0; - + //tell the GUI gui.setSmoothFac(smoothFac[smoothFac_ind]); - + //update the button gui.smoothingButton.but_txt = "Smooth\n" + smoothFac[smoothFac_ind]; } void toggleShowPolarity() { gui.headPlot1.use_polarity = !gui.headPlot1.use_polarity; - + //update the button gui.showPolarityButton.but_txt = "Polarity\n" + gui.headPlot1.getUsePolarityTrueFalse(); } @@ -1305,8 +1312,8 @@ void fileSelected(File selection) { //called by the Open File dialog box after } } -void verbosePrint(String _string){ - if(isVerbose){ +void verbosePrint(String _string) { + if (isVerbose) { println(_string); } } @@ -1314,8 +1321,28 @@ void verbosePrint(String _string){ void delay(int delay) { int time = millis(); - while(millis() - time <= delay); + while (millis() - time <= delay); +} + + +// created 2/10/16 by Conor Russomanno to dissect the aspects of the GUI that are slowing it down +// here I will create methods used to identify where there are inefficiencies in the code +// note to self: make sure to check the frameRate() in setup... switched from 16 to 30... working much faster now... still a useful method below. +// -------------------------------------------------------------- START ------------------------------------------------------------------------------- +boolean printSignPosts = false; + +float millisOfLastSignPost = 0.0; +float millisSinceLastSignPost = 0.0; + +//method for printing out an ["indentifier"][millisSinceLastSignPost] for debugging purposes... allows us to look at what is taking too long. +void signPost(String identifier) { + if (printSignPosts) { + millisSinceLastSignPost = millis() - millisOfLastSignPost; + println("SIGN POST: [" + identifier + "][" + millisSinceLastSignPost + "]"); + millisOfLastSignPost = millis(); + } } +// ---------------------------------------------------------------- FINISH ----------------------------------------------------------------------------- // here's a function to catch whenever the window is being closed, so that // it stops OpenBCI diff --git a/OpenBCI_GUI/Spectrogram.pde b/OpenBCI_GUI/Spectrogram.pde old mode 100755 new mode 100644 index fbd0297..7112a67 --- a/OpenBCI_GUI/Spectrogram.pde +++ b/OpenBCI_GUI/Spectrogram.pde @@ -163,21 +163,16 @@ class Spectrogram { } public void draw(int x, int y, int w, int h,float max_freq_Hz) { - if (false) { - //draw the whole image - image(img,x,y,w,h); - } else { - //float max_freq_Hz = freq_lim_Hz[1]; - int max_ind = 0; - while ((localFftData.indexToFreq(max_ind) <= max_freq_Hz) & (max_ind < localFftData.specSize()-1)) max_ind++; - //println("Spectrogram.draw(): max_ind = " + max_ind); - //PImage foo = (PImage)(img.get(0,localFftData.specSize()-1-max_ind,Nslices,localFftData.specSize()-1)).clone(); - //println("spectrogram.draw() max freq = " + localFftData.indexToFreq(max_ind)); - int img_x = 0; - int img_y = localFftData.specSize()-1-max_ind; - int img_w = Nslices - img_x + 1; - int img_h = localFftData.specSize()-1 - img_y + 1; - image(img.get(img_x,img_y,img_w,img_h),x,y,w,h); //plot a subset - } + //float max_freq_Hz = freq_lim_Hz[1]; + int max_ind = 0; + while ((localFftData.indexToFreq(max_ind) <= max_freq_Hz) & (max_ind < localFftData.specSize()-1)) max_ind++; + //println("Spectrogram.draw(): max_ind = " + max_ind); + //PImage foo = (PImage)(img.get(0,localFftData.specSize()-1-max_ind,Nslices,localFftData.specSize()-1)).clone(); + //println("spectrogram.draw() max freq = " + localFftData.indexToFreq(max_ind)); + int img_x = 0; + int img_y = localFftData.specSize()-1-max_ind; + int img_w = Nslices - img_x + 1; + int img_h = localFftData.specSize()-1 - img_y + 1; + image(img.get(img_x,img_y,img_w,img_h),x,y,w,h); //plot a subset } -} +} \ No newline at end of file diff --git a/libraries/controlP5/src/controlP5/ControlP5.java b/libraries/controlP5/src/controlP5/ControlP5.java index 9a8b648..bed396f 100644 --- a/libraries/controlP5/src/controlP5/ControlP5.java +++ b/libraries/controlP5/src/controlP5/ControlP5.java @@ -237,7 +237,7 @@ public void keyEvent( ) { static int welcome = 0; private void welcome( ) { - System.out.println( "ControlP5 " + VERSION + " " + "infos, comments, questions at http://www.sojamo.de/libraries/controlP5" ); + // System.out.println( "ControlP5 " + VERSION + " " + "infos, comments, questions at http://www.sojamo.de/libraries/controlP5" ); } public ControlP5 setGraphics( PApplet theApplet , int theX , int theY ) {