diff --git a/CHANGELOG.md b/CHANGELOG.md index f8356817b..2ccf3d8b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Improvements - Update to BrainFlow 5.6.1 - Add feature to connect to Ganglion using Native Bluetooth #1080 +- Refactor the creation and playback of OpenBCI GUI CSV files #1119 # v5.1.0 diff --git a/OpenBCI_GUI/BatteryInfoCapableBoard.pde b/OpenBCI_GUI/BatteryInfoCapableBoard.pde deleted file mode 100644 index 53deb4305..000000000 --- a/OpenBCI_GUI/BatteryInfoCapableBoard.pde +++ /dev/null @@ -1,9 +0,0 @@ - -interface BatteryInfoCapableBoard { - - public Integer getBatteryChannel(); - - public List getDataWithBatteryInfo(int maxSamples); - - public int getBatteryInfoSampleRate(); -}; diff --git a/OpenBCI_GUI/BoardBrainFlowSynthetic.pde b/OpenBCI_GUI/BoardBrainFlowSynthetic.pde index 75f597212..b77c3f2f6 100644 --- a/OpenBCI_GUI/BoardBrainFlowSynthetic.pde +++ b/OpenBCI_GUI/BoardBrainFlowSynthetic.pde @@ -2,13 +2,9 @@ import brainflow.*; import org.apache.commons.lang3.tuple.Pair; -class BoardBrainFlowSynthetic extends BoardBrainFlow -implements AccelerometerCapableBoard, PPGCapableBoard, EDACapableBoard, BatteryInfoCapableBoard { +class BoardBrainFlowSynthetic extends BoardBrainFlow implements AccelerometerCapableBoard { private int[] accelChannelsCache = null; - private int[] edaChannelsCache = null; - private int[] ppgChannelsCache = null; - private Integer batteryChannelCache = null; private int numChannels = 0; private volatile boolean[] activeChannels = null; @@ -97,80 +93,12 @@ implements AccelerometerCapableBoard, PPGCapableBoard, EDACapableBoard, BatteryI return accelChannelsCache; } - @Override - public boolean isPPGActive() { - return true; - } - - @Override - public void setPPGActive(boolean active) { - outputWarn("PPG is always active for BrainflowSyntheticBoard"); - } - - @Override - public int[] getPPGChannels() { - if(ppgChannelsCache == null) { - try { - ppgChannelsCache = BoardShim.get_ppg_channels(getBoardIdInt()); - - } catch (BrainFlowError e) { - e.printStackTrace(); - } - } - - return ppgChannelsCache; - } - - @Override - public boolean isEDAActive() { - return true; - } - - @Override - public void setEDAActive(boolean active) { - outputWarn("EDA is always active for BrainflowSyntheticBoard"); - } - - @Override - public int[] getEDAChannels() { - if (edaChannelsCache == null) { - try { - edaChannelsCache = BoardShim.get_eda_channels(getBoardIdInt()); - - } catch (BrainFlowError e) { - e.printStackTrace(); - } - } - - return edaChannelsCache; - } - - @Override - public Integer getBatteryChannel() { - if (batteryChannelCache == null) { - try { - batteryChannelCache = BoardShim.get_battery_channel(getBoardIdInt()); - } catch (BrainFlowError e) { - e.printStackTrace(); - - } - } - - return batteryChannelCache; - } @Override protected void addChannelNamesInternal(String[] channelNames) { - for (int i=0; i getDataWithPPG(int maxSamples) { - return getData(maxSamples); - } - - @Override - public List getDataWithEDA(int maxSamples) { - return getData(maxSamples); - } - - @Override - public List getDataWithBatteryInfo(int maxSamples) { - return getData(maxSamples); - } - @Override public int getAccelSampleRate() { return getSampleRate(); } - - @Override - public int getPPGSampleRate() { - return getSampleRate(); - } - - @Override - public int getEDASampleRate() { - return getSampleRate(); - } - - @Override - public int getBatteryInfoSampleRate() { - return getSampleRate(); - } }; diff --git a/OpenBCI_GUI/CustomCp5Classes.pde b/OpenBCI_GUI/CustomCp5Classes.pde index ced72f01b..0bcbc8c57 100644 --- a/OpenBCI_GUI/CustomCp5Classes.pde +++ b/OpenBCI_GUI/CustomCp5Classes.pde @@ -130,6 +130,7 @@ class ButtonHelpText{ //////////////////////////////////////////////////////////////////////////////////// // MENULIST CLASS // // Based on ControlP5 Processing Library example, written by Andreas Schlegel // +// WARNING: This class does not respond well to being resized -RW 5/5/23 // //////////////////////////////////////////////////////////////////////////////////// public class MenuList extends controlP5.Controller { diff --git a/OpenBCI_GUI/DataSourcePlayback.pde b/OpenBCI_GUI/DataSourcePlayback.pde index 31c372700..5ef3feee8 100644 --- a/OpenBCI_GUI/DataSourcePlayback.pde +++ b/OpenBCI_GUI/DataSourcePlayback.pde @@ -1,35 +1,34 @@ -class DataSourcePlayback implements DataSource, AccelerometerCapableBoard, AnalogCapableBoard, DigitalCapableBoard, EDACapableBoard, PPGCapableBoard, BatteryInfoCapableBoard, FileBoard { - private String playbackFilePath; - private ArrayList rawData; - private int currentSample; - private int timeOfLastUpdateMS; +abstract class DataSourcePlayback implements DataSource, FileBoard { + private String playbackFilePathExg; + private ArrayList rawDataExg; + private int currentSampleExg; + private int timeOfLastUpdateMSExg; private String underlyingClassName; - private Integer batteryChannelCache = null; - private int numNewSamplesThisFrame; + private int numNewSamplesThisFrameExg; private boolean initialized = false; private boolean streaming = false; - private Board underlyingBoard = null; - private int sampleRate = -1; - private int numChannels = 0; // use it instead getTotalChannelCount() method for old playback files + public Board underlyingBoard = null; + private int sampleRateExg = -1; + private int numChannelsExg = 0; // use it instead getTotalChannelCount() method for old playback files DataSourcePlayback(String filePath) { - playbackFilePath = filePath; + playbackFilePathExg = filePath; } @Override public boolean initialize() { - currentSample = 0; - String[] lines = loadStrings(playbackFilePath); + currentSampleExg = 0; + String[] lines = loadStrings(playbackFilePathExg); - if(!parseHeader(lines)) { + if(!parseExgHeader(lines)) { return false; } if(!instantiateUnderlyingBoard()) { return false; } - if(!parseData(lines)) { + if(!parseExgData(lines)) { return false; } @@ -41,7 +40,7 @@ class DataSourcePlayback implements DataSource, AccelerometerCapableBoard, Analo initialized = false; } - protected boolean parseHeader(String[] lines) { + protected boolean parseExgHeader(String[] lines) { for (String line : lines) { if (!line.startsWith("%")) { break; // reached end of header @@ -61,7 +60,7 @@ class DataSourcePlayback implements DataSource, AccelerometerCapableBoard, Analo int endIndex = line.indexOf("Hz") - 1; String hzString = line.substring(startIndex, endIndex); - sampleRate = Integer.parseInt(hzString); + sampleRateExg = Integer.parseInt(hzString); } // used to figure out the underlying board type @@ -71,7 +70,7 @@ class DataSourcePlayback implements DataSource, AccelerometerCapableBoard, Analo } } - boolean success = sampleRate > 0 && underlyingClassName != ""; + boolean success = sampleRateExg > 0 && underlyingClassName != ""; if(!success) { outputError("Playback file does not contain the required header data."); } @@ -95,7 +94,7 @@ class DataSourcePlayback implements DataSource, AccelerometerCapableBoard, Analo return underlyingBoard != null; } - protected boolean parseData(String[] lines) { + protected boolean parseExgData(String[] lines) { int dataStart; // set data start to first line of data (skip header) for (dataStart = 0; dataStart < lines.length; dataStart++) { @@ -107,21 +106,21 @@ class DataSourcePlayback implements DataSource, AccelerometerCapableBoard, Analo } int dataLength = lines.length - dataStart; - rawData = new ArrayList(dataLength); + rawDataExg = new ArrayList(dataLength); for (int iData=0; iData list = getData(numNewSamplesThisFrame); - for (int i = 0; i < numNewSamplesThisFrame; i++) { - for (int j = 0; j < numChannels; j++) { + double[][] array = new double[numChannelsExg][numNewSamplesThisFrameExg]; + List list = getData(numNewSamplesThisFrameExg); + for (int i = 0; i < numNewSamplesThisFrameExg; i++) { + for (int j = 0; j < numChannelsExg; j++) { array[j][i] = list.get(i)[j]; } } @@ -275,14 +244,14 @@ class DataSourcePlayback implements DataSource, AccelerometerCapableBoard, Analo @Override public List getData(int maxSamples) { - int firstSample = max(0, currentSample - maxSamples); - List result = rawData.subList(firstSample, currentSample); + int firstSample = max(0, currentSampleExg - maxSamples); + List result = rawDataExg.subList(firstSample, currentSampleExg); // if needed, pad the beginning of the array with empty data - if (maxSamples > currentSample) { - int sampleDiff = maxSamples - currentSample; + if (maxSamples > currentSampleExg) { + int sampleDiff = maxSamples - currentSampleExg; - double[] emptyData = new double[numChannels]; + double[] emptyData = new double[numChannelsExg]; ArrayList newResult = new ArrayList(maxSamples); for (int i=0; i= getTotalSamples(); } - @Override - public void setPPGActive(boolean active) { - // nothing - } +} - @Override - public int[] getPPGChannels() { - if (underlyingBoard instanceof PPGCapableBoard) { - return ((PPGCapableBoard)underlyingBoard).getPPGChannels(); +public DataSourcePlayback getDataSourcePlaybackClassFromFile(String path) { + verbosePrint("Checking " + path + " for underlying board class."); + String strCurrentLine; + int lineCounter = 0; + int maxLinesToCheck = 4; + String infoToCheck = "%Board = "; + String underlyingBoardClassName = ""; + BufferedReader reader = createBufferedReader(path); + try { + while (lineCounter < maxLinesToCheck) { + strCurrentLine = reader.readLine(); + verbosePrint(strCurrentLine); + if (strCurrentLine.startsWith(infoToCheck)) { + String[] splitCurrentLine = split(strCurrentLine, "OpenBCI_GUI$"); + underlyingBoardClassName = splitCurrentLine[1]; + } + lineCounter++; } - - return new int[0]; - } - - @Override - public Integer getBatteryChannel() { - if (batteryChannelCache == null && underlyingBoard instanceof BatteryInfoCapableBoard) { - try { - batteryChannelCache = BoardShim.get_battery_channel(((BoardBrainFlow)underlyingBoard).getBoardIdInt()); - } catch (BrainFlowError e) { - e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (reader != null) { + reader.close(); } + } catch (IOException ex) { + ex.printStackTrace(); } - - return batteryChannelCache; - } - - @Override - public boolean endOfFileReached() { - return currentSample >= getTotalSamples(); - } - - @Override - public List getDataWithBatteryInfo(int maxSamples) { - return getData(maxSamples); - } - - @Override - public List getDataWithAnalog(int maxSamples) { - return getData(maxSamples); } - - @Override - public List getDataWithDigital(int maxSamples) { - return getData(maxSamples); - } - - @Override - public List getDataWithAccel(int maxSamples) { - return getData(maxSamples); - } - - @Override - public List getDataWithPPG(int maxSamples) { - return getData(maxSamples); - } - - @Override - public List getDataWithEDA(int maxSamples) { - return getData(maxSamples); + + switch (underlyingBoardClassName) { + case ("BoardCytonSerial"): + case ("BoardCytonSerialDaisy"): + case ("BoardCytonWifi"): + case ("BoardCytonWifiDaisy"): + return new DataSourcePlaybackCyton(path); + case ("BoardGanglionBLE"): + case ("BoardGanglionNative"): + case ("BoardGanglionWifi"): + return new DataSourcePlaybackGanglion(path); + case ("BoardBrainFlowSynthetic"): + return new DataSourcePlaybackSynthetic(path); + default: + return null; } - } diff --git a/OpenBCI_GUI/DataSourcePlaybackCyton.pde b/OpenBCI_GUI/DataSourcePlaybackCyton.pde new file mode 100644 index 000000000..21bb120f0 --- /dev/null +++ b/OpenBCI_GUI/DataSourcePlaybackCyton.pde @@ -0,0 +1,109 @@ +class DataSourcePlaybackCyton extends DataSourcePlayback implements AccelerometerCapableBoard, AnalogCapableBoard, DigitalCapableBoard, FileBoard { + + DataSourcePlaybackCyton(String filePath) { + super(filePath); + } + + @Override + public int getAccelSampleRate() { + return getSampleRate(); + } + + @Override + public int getAnalogSampleRate() { + return getSampleRate(); + } + + @Override + public int getDigitalSampleRate() { + return getSampleRate(); + } + + @Override + public boolean isAccelerometerActive() { + return underlyingBoard instanceof AccelerometerCapableBoard; + } + + @Override + public void setAccelerometerActive(boolean active) { + // nothing + } + + @Override + public boolean canDeactivateAccelerometer() { + return false; + } + + @Override + public int[] getAccelerometerChannels() { + if (underlyingBoard instanceof AccelerometerCapableBoard) { + return ((AccelerometerCapableBoard)underlyingBoard).getAccelerometerChannels(); + } + + return new int[0]; + } + + @Override + public boolean isAnalogActive() { + return underlyingBoard instanceof AnalogCapableBoard; + } + + @Override + public void setAnalogActive(boolean active) { + // nothing + } + + @Override + public boolean canDeactivateAnalog() { + return false; + } + + @Override + public int[] getAnalogChannels() { + if (underlyingBoard instanceof AnalogCapableBoard) { + return ((AnalogCapableBoard)underlyingBoard).getAnalogChannels(); + } + + return new int[0]; + } + + @Override + public boolean isDigitalActive() { + return underlyingBoard instanceof DigitalCapableBoard; + } + + @Override + public void setDigitalActive(boolean active) { + // nothing + } + + @Override + public boolean canDeactivateDigital() { + return false; + } + + @Override + public int[] getDigitalChannels() { + if (underlyingBoard instanceof DigitalCapableBoard) { + return ((DigitalCapableBoard)underlyingBoard).getDigitalChannels(); + } + + return new int[0]; + } + + @Override + public List getDataWithAnalog(int maxSamples) { + return getData(maxSamples); + } + + @Override + public List getDataWithDigital(int maxSamples) { + return getData(maxSamples); + } + + @Override + public List getDataWithAccel(int maxSamples) { + return getData(maxSamples); + } + +} diff --git a/OpenBCI_GUI/DataSourcePlaybackGanglion.pde b/OpenBCI_GUI/DataSourcePlaybackGanglion.pde new file mode 100644 index 000000000..57a581740 --- /dev/null +++ b/OpenBCI_GUI/DataSourcePlaybackGanglion.pde @@ -0,0 +1,41 @@ +class DataSourcePlaybackGanglion extends DataSourcePlayback implements AccelerometerCapableBoard, FileBoard { + + DataSourcePlaybackGanglion(String filePath) { + super(filePath); + } + + @Override + public int getAccelSampleRate() { + return getSampleRate(); + } + + @Override + public boolean isAccelerometerActive() { + return underlyingBoard instanceof AccelerometerCapableBoard; + } + + @Override + public void setAccelerometerActive(boolean active) { + // nothing + } + + @Override + public boolean canDeactivateAccelerometer() { + return false; + } + + @Override + public int[] getAccelerometerChannels() { + if (underlyingBoard instanceof AccelerometerCapableBoard) { + return ((AccelerometerCapableBoard)underlyingBoard).getAccelerometerChannels(); + } + + return new int[0]; + } + + @Override + public List getDataWithAccel(int maxSamples) { + return getData(maxSamples); + } + +} diff --git a/OpenBCI_GUI/DataSourcePlaybackSynthetic.pde b/OpenBCI_GUI/DataSourcePlaybackSynthetic.pde new file mode 100644 index 000000000..01ce69ef4 --- /dev/null +++ b/OpenBCI_GUI/DataSourcePlaybackSynthetic.pde @@ -0,0 +1,53 @@ +class DataSourcePlaybackSynthetic extends DataSourcePlayback implements AccelerometerCapableBoard, FileBoard { + + DataSourcePlaybackSynthetic(String filePath) { + super(filePath); + } + + protected boolean instantiateUnderlyingBoard() { + try { + underlyingBoard = new BoardBrainFlowSynthetic(nchan); + } catch (Exception e) { + println(e.getMessage()); + e.printStackTrace(); + return false; + } + + return underlyingBoard != null; + } + + @Override + public int getAccelSampleRate() { + return getSampleRate(); + } + + @Override + public boolean isAccelerometerActive() { + return underlyingBoard instanceof AccelerometerCapableBoard; + } + + @Override + public void setAccelerometerActive(boolean active) { + // nothing + } + + @Override + public boolean canDeactivateAccelerometer() { + return false; + } + + @Override + public int[] getAccelerometerChannels() { + if (underlyingBoard instanceof AccelerometerCapableBoard) { + return ((AccelerometerCapableBoard)underlyingBoard).getAccelerometerChannels(); + } + + return new int[0]; + } + + @Override + public List getDataWithAccel(int maxSamples) { + return getData(maxSamples); + } + +} diff --git a/OpenBCI_GUI/DataWriterAuxODF.pde b/OpenBCI_GUI/DataWriterAuxODF.pde index 924dcd369..86b552d94 100644 --- a/OpenBCI_GUI/DataWriterAuxODF.pde +++ b/OpenBCI_GUI/DataWriterAuxODF.pde @@ -1,67 +1,30 @@ - -// todo refactor to avoid copypaste with DataWriterODF -//write data to a text file -public class DataWriterAuxODF { - private PrintWriter output; - private String fname; - private int rowsWritten; - private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - - private AuxDataBoard streamingBoard; +public class DataWriterAuxODF extends DataWriterODF { + protected String fileNamePrependString = "OpenBCI-RAW-Aux-"; + protected String headerFirstLineString = "%OpenBCI Raw Aux Data"; //variation on constructor to have custom name DataWriterAuxODF(String _sessionName, String _fileName) { - streamingBoard = (AuxDataBoard)currentBoard; - fname = settings.getSessionPath(); - fname += "OpenBCI-RAW-Aux-"; - fname += _fileName; - fname += ".txt"; - output = createWriter(fname); //open the file - writeHeader(); //add the header - rowsWritten = 0; //init the counter + super(_sessionName, _fileName); } - - public void writeHeader() { - output.println("%OpenBCI Raw Aux Data"); - output.println("%Number of channels = " + streamingBoard.getNumAuxChannels()); - output.println("%Sample Rate = " + streamingBoard.getAuxSampleRate() + " Hz"); - output.println("%Board = " + streamingBoard.getClass().getName()); - - String[] colNames = streamingBoard.getAuxChannelNames(); - - for (int i=0; i getDataWithEDA(int maxSamples); - - public int getEDASampleRate(); -}; diff --git a/OpenBCI_GUI/Extras.pde b/OpenBCI_GUI/Extras.pde index fe1e5b9ae..3f3a2f759 100644 --- a/OpenBCI_GUI/Extras.pde +++ b/OpenBCI_GUI/Extras.pde @@ -8,6 +8,9 @@ import static java.util.prefs.Preferences.systemRoot; // Global Functions //------------------------------------------------------------------------ +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * @description Helper function to determine if the system is linux or not. * @return {boolean} true if os is linux, false otherwise. @@ -263,7 +266,26 @@ String dropNonPrintableChars(String myString) break; } } - return newString.toString(); + String res = newString.toString(); + res = res.replace("\r", ""); + res = res.replace("\n", ""); + res = res.replace("\t", ""); + return res; +} + +String getIpAddrFromStr(String strWithIP) { + String temp = dropNonPrintableChars(strWithIP); + String IPADDRESS_PATTERN = + "(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"; + Pattern pattern = Pattern.compile(IPADDRESS_PATTERN); + Matcher matcher = pattern.matcher(temp); + if (matcher.find()) { + return matcher.group(); + } else{ + output("Invalid Ip address"); + println("Provided Ip address doesn't match regexp"); + return ""; + } } float getFontStringHeight(PFont _font, String string) { @@ -440,22 +462,21 @@ class RectDimensions { class DataStatus { public boolean is_railed; - private double threshold_railed; public boolean is_railed_warn; - private double threshold_railed_warn; private double percentage; public String notificationString; private final color default_color = OPENBCI_DARKBLUE; private final color yellow = SIGNAL_CHECK_YELLOW; private final color red = BOLD_RED; private color colorIndicator = default_color; + // thresholds are pecentages of max possible value + private double threshold_railed = 90.0; + private double threshold_railed_warn = 75.0; - DataStatus(double thresh_railed, double thresh_railed_warn) { + DataStatus() { notificationString = ""; is_railed = false; - threshold_railed = thresh_railed; is_railed_warn = false; - threshold_railed_warn = thresh_railed_warn; percentage = 0.0; } // here data is a full range for 20sec of data and doesnt take in account window size @@ -653,6 +674,10 @@ class TextBox { textColor = c; } + public void setBackgroundColor(color c) { + backgroundColor = c; + } + public int getWidth() { return w; } @@ -686,3 +711,46 @@ public boolean pingWebsite(String url) { } } + +public BufferedReader createBufferedReader(String filepath) { + File file; + BufferedReader reader; + try { + file = new File(filepath); + reader = new BufferedReader(new FileReader(file)); + return reader; + } catch (IOException e) { + e.printStackTrace(); + return null; + } +} + +//Used to check for one string in a text file +//Uses a buffered reader for this method so that we do not load entire file to memory +boolean checkTextFileForInfo(String path, String infoToCheck, int maxLinesToCheck) { + verbosePrint("Checking " + path + " for " + infoToCheck); + String strCurrentLine; + int lineCounter = 0; + BufferedReader reader = createBufferedReader(path); + try { + while (lineCounter < maxLinesToCheck) { + strCurrentLine = reader.readLine(); + verbosePrint(strCurrentLine); + if (strCurrentLine.equals(infoToCheck)) { + return true; + } + lineCounter++; + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (reader != null) { + reader.close(); + } + } catch (IOException ex) { + ex.printStackTrace(); + } + } + return false; +} diff --git a/OpenBCI_GUI/OpenBCI_GUI.pde b/OpenBCI_GUI/OpenBCI_GUI.pde index 67c8d1c78..8569825ca 100644 --- a/OpenBCI_GUI/OpenBCI_GUI.pde +++ b/OpenBCI_GUI/OpenBCI_GUI.pde @@ -61,8 +61,8 @@ import http.requests.*; // Global Variables & Instances //------------------------------------------------------------------------ //Used to check GUI version in TopNav.pde and displayed on the splash screen on startup -String localGUIVersionString = "v5.1.1-alpha.2"; -String localGUIVersionDate = "February 2023"; +String localGUIVersionString = "v5.1.1-alpha.3"; +String localGUIVersionDate = "May 2023"; String guiLatestVersionGithubAPI = "https://api.github.com/repos/OpenBCI/OpenBCI_GUI/releases/latest"; String guiLatestReleaseLocation = "https://github.com/OpenBCI/OpenBCI_GUI/releases/latest"; Boolean guiIsUpToDate; @@ -139,9 +139,6 @@ int nchan = NCHAN_CYTON; //Normally, 8 or 16. Choose a smaller number to show f //define variables related to warnings to the user about whether the EEG data is nearly railed (and, therefore, of dubious quality) DataStatus is_railed[]; -// thresholds are pecentages of max possible value -final double threshold_railed = 99.0; -final double threshold_railed_warn = 90.0; //Cyton SD Card setting CytonSDMode cyton_sdSetting = CytonSDMode.NO_WRITE; @@ -589,7 +586,7 @@ void initSystem() { break; case DATASOURCE_PLAYBACKFILE: if (!playbackData_fname.equals("N/A")) { - currentBoard = new DataSourcePlayback(playbackData_fname); + currentBoard = getDataSourcePlaybackClassFromFile(playbackData_fname); println("OpenBCI_GUI: Init session using Playback data source"); } else { if (!sdData_fname.equals("N/A")) { @@ -757,7 +754,7 @@ void initCoreDataObjects() { data_elec_imp_ohm = new float[nchan]; is_railed = new DataStatus[nchan]; for (int i=0; i getDataWithPPG(int maxSamples); - - public int getPPGSampleRate(); -}; diff --git a/OpenBCI_GUI/SessionSettings.pde b/OpenBCI_GUI/SessionSettings.pde index 865dfb2d3..e528f9a4a 100644 --- a/OpenBCI_GUI/SessionSettings.pde +++ b/OpenBCI_GUI/SessionSettings.pde @@ -1027,14 +1027,14 @@ class SessionSettings { } else if (dataSource == DATASOURCE_GANGLION) { filePath += fileNames[2]; } else if (dataSource == DATASOURCE_PLAYBACKFILE) { - filePath += fileNames[4]; + filePath += fileNames[3]; } else if (dataSource == DATASOURCE_SYNTHETIC) { if (_nchan == NCHAN_GANGLION) { - filePath += fileNames[5]; + filePath += fileNames[4]; } else if (_nchan == NCHAN_CYTON) { - filePath += fileNames[6]; + filePath += fileNames[5]; } else { - filePath += fileNames[7]; + filePath += fileNames[6]; } } } diff --git a/OpenBCI_GUI/SignalCheckThresholds.pde b/OpenBCI_GUI/SignalCheckThresholds.pde index a7092208e..94d698814 100644 --- a/OpenBCI_GUI/SignalCheckThresholds.pde +++ b/OpenBCI_GUI/SignalCheckThresholds.pde @@ -15,7 +15,7 @@ class SignalCheckThresholdUI { signalCheckMode = _mode; name = _name; textColor = _textColor; - defaultValue_Percentage = name.equals("errorThreshold") ? (int)threshold_railed : (int)threshold_railed_warn; + defaultValue_Percentage = name.equals("errorThreshold") ? 90 : 75; valuePercentage = defaultValue_Percentage; defaultValue_kOhms = name == "errorThreshold" ? 2500 : 750; valuekOhms = defaultValue_kOhms; diff --git a/OpenBCI_GUI/W_AnalogRead.pde b/OpenBCI_GUI/W_AnalogRead.pde index 86e72abe5..178ace8da 100644 --- a/OpenBCI_GUI/W_AnalogRead.pde +++ b/OpenBCI_GUI/W_AnalogRead.pde @@ -94,8 +94,11 @@ class W_AnalogRead extends Widget { void update() { super.update(); //calls the parent update() method of Widget (DON'T REMOVE) - if(currentBoard instanceof DataSourcePlayback && !((DataSourcePlayback)currentBoard).isAnalogActive()) { - return; + if (currentBoard instanceof DataSourcePlayback) { + if (((DataSourcePlayback)currentBoard) instanceof AnalogCapableBoard + && (!((AnalogCapableBoard)currentBoard).isAnalogActive())) { + return; + } } //update channel bars ... this means feeding new EEG data into plots diff --git a/OpenBCI_GUI/W_DigitalRead.pde b/OpenBCI_GUI/W_DigitalRead.pde index 2ff57e7f8..38b593a4d 100644 --- a/OpenBCI_GUI/W_DigitalRead.pde +++ b/OpenBCI_GUI/W_DigitalRead.pde @@ -84,8 +84,11 @@ class W_DigitalRead extends Widget { public void update() { super.update(); //calls the parent update() method of Widget (DON'T REMOVE) - if(currentBoard instanceof DataSourcePlayback && !((DataSourcePlayback)currentBoard).isDigitalActive()) { - return; + if (currentBoard instanceof DataSourcePlayback) { + if (((DataSourcePlayback)currentBoard) instanceof DigitalCapableBoard + && (!((DigitalCapableBoard)currentBoard).isDigitalActive())) { + return; + } } //update channel bars ... this means feeding new EEG data into plots diff --git a/OpenBCI_GUI/W_Playback.pde b/OpenBCI_GUI/W_Playback.pde index 410b8e3f9..a9cb921e0 100644 --- a/OpenBCI_GUI/W_Playback.pde +++ b/OpenBCI_GUI/W_Playback.pde @@ -224,7 +224,7 @@ boolean playbackFileSelected (String longName, String shortName) { try { BufferedReader brTest = new BufferedReader(new FileReader(longName)); String line = brTest.readLine(); - if (line.equals("%OpenBCI Raw EEG Data")) { + if (line.equals("%OpenBCI Raw EEG Data") || line.equals("%OpenBCI Raw EXG Data")) { verbosePrint("PLAYBACK: Found OpenBCI Header in File!"); sdData_fname = "N/A"; for (int i = 0; i < 3; i++) { diff --git a/OpenBCI_GUI/W_PulseSensor.pde b/OpenBCI_GUI/W_PulseSensor.pde index 1185424c8..c010db895 100644 --- a/OpenBCI_GUI/W_PulseSensor.pde +++ b/OpenBCI_GUI/W_PulseSensor.pde @@ -11,13 +11,11 @@ class W_PulseSensor extends Widget { //to see all core variables/methods of the Widget class, refer to Widget.pde //put your custom variables here... - - color graphStroke = #d2d2d2; color graphBG = #f5f5f5; color textColor = #000000; -// Pulse Sensor Visualizer Stuff + // Pulse Sensor Visualizer Stuff int count = 0; int heart = 0; int PulseBuffSize = 3*currentBoard.getSampleRate(); // Originally 400 @@ -91,8 +89,11 @@ class W_PulseSensor extends Widget { void update(){ super.update(); //calls the parent update() method of Widget (DON'T REMOVE) - if(currentBoard instanceof DataSourcePlayback && !((DataSourcePlayback)currentBoard).isAnalogActive()) { - return; + if(currentBoard instanceof DataSourcePlayback) { + if (((DataSourcePlayback)currentBoard) instanceof AnalogCapableBoard + && (!((AnalogCapableBoard)currentBoard).isAnalogActive())) { + return; + } } List allData = currentBoard.getData(PulseBuffSize);