Skip to content

Commit 2ba150a

Browse files
committed
Add accumulated data queues to background processing when Networking widget is closed
Also, process Digital Read in the background
1 parent 1d6d62d commit 2ba150a

2 files changed

Lines changed: 154 additions & 32 deletions

File tree

OpenBCI_GUI/DataProcessing.pde

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,5 +307,7 @@ class DataProcessing {
307307
if (w_pulsesensor != null) {
308308
w_pulsesensor.updatePulseSensorWidgetData();
309309
}
310+
311+
w_networking.updateNetworkingWidgetData();
310312
}
311313
}

OpenBCI_GUI/W_Networking.pde

Lines changed: 152 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,22 @@ class W_Networking extends Widget {
8888
private LinkedList<double[]> dataAccumulationQueue;
8989
private LinkedList<float[]> dataAccumulationQueueFiltered;
9090
private LinkedList<Double> markerDataAccumulationQueue;
91+
private LinkedList<double[]> accelDataAccumulationQueue;
92+
private LinkedList<double[]> digitalDataAccumulationQueue;
93+
private LinkedList<double[]> analogDataAccumulationQueue;
9194
public float[][] dataBufferToSend;
9295
public float[][] dataBufferToSend_Filtered;
9396
public float[] markerDataBufferToSend;
97+
public float[][] accelDataBufferToSend;
98+
public float[][] digitalDataBufferToSend;
99+
public float[][] analogDataBufferToSend;
94100
public AtomicBoolean[] networkingFrameLocks = new AtomicBoolean[4];
95101
public AtomicBoolean newTimeSeriesDataToSend = new AtomicBoolean(false);
96102
public AtomicBoolean newTimeSeriesDataToSendFiltered = new AtomicBoolean(false);
97103
public AtomicBoolean newMarkerDataToSend = new AtomicBoolean(false);
104+
public AtomicBoolean newAccelDataToSend = new AtomicBoolean(false);
105+
public AtomicBoolean newDigitalDataToSend = new AtomicBoolean(false);
106+
public AtomicBoolean newAnalogDataToSend = new AtomicBoolean(false);
98107

99108
public HashMap<String, Object> cp5Map = new HashMap<String, Object>();
100109

@@ -146,6 +155,12 @@ class W_Networking extends Widget {
146155
dataAccumulationQueueFiltered = new LinkedList<float[]>();
147156
markerDataBufferToSend = new float[nPointsPerUpdate];
148157
markerDataAccumulationQueue = new LinkedList<Double>();
158+
accelDataBufferToSend = new float[3][nPointsPerUpdate];
159+
accelDataAccumulationQueue = new LinkedList<double[]>();
160+
digitalDataBufferToSend = new float[5][nPointsPerUpdate];
161+
digitalDataAccumulationQueue = new LinkedList<double[]>();
162+
analogDataBufferToSend = new float[3][nPointsPerUpdate];
163+
analogDataAccumulationQueue = new LinkedList<double[]>();
149164

150165
cp5ElementsToCheck = new ArrayList<controlP5.Controller>();
151166
cp5ElementsToCheck.add((controlP5.Controller) guideButton);
@@ -253,17 +268,21 @@ class W_Networking extends Widget {
253268
previousCP5State = cp5ElementsAreActive;
254269
}
255270

256-
if (currentBoard.isStreaming()) {
257-
accumulateNewData();
258-
checkIfEnoughDataToSend();
259-
}
260-
261271
// Check if any textfields are active and also for copy/paste if active
262272
updateNetworkingTextfields();
263273
}
264274

265-
public void accumulateNewData() {
266-
// accumulate data
275+
// Call this function in DataProcessing.pde to update the data buffers even if the widget is not visible
276+
public void updateNetworkingWidgetData() {
277+
if (!currentBoard.isStreaming()) {
278+
return;
279+
}
280+
281+
accumulateNewData();
282+
checkIfEnoughDataToSend();
283+
}
284+
285+
private void accumulateNewData() {
267286
double[][] newData = currentBoard.getFrameData();
268287
int[] exgChannels = currentBoard.getEXGChannels();
269288
int markerChannel = currentBoard.getMarkerChannel();
@@ -287,10 +306,44 @@ class W_Networking extends Widget {
287306
dataAccumulationQueue.add(sample);
288307
dataAccumulationQueueFiltered.add(sample_filtered);
289308
markerDataAccumulationQueue.add(newData[markerChannel][iSample]);
309+
310+
if (currentBoard instanceof AccelerometerCapableBoard) {
311+
AccelerometerCapableBoard accelBoard = (AccelerometerCapableBoard) currentBoard;
312+
int[] accelChannels = accelBoard.getAccelerometerChannels();
313+
double[] accelSample = new double[accelChannels.length];
314+
for (int iChan = 0; iChan < accelChannels.length; iChan++) {
315+
accelSample[iChan] = newData[accelChannels[iChan]][iSample];
316+
}
317+
accelDataAccumulationQueue.add(accelSample);
318+
}
319+
320+
if (currentBoard instanceof DigitalCapableBoard) {
321+
DigitalCapableBoard digitalBoard = (DigitalCapableBoard) currentBoard;
322+
if (digitalBoard.isDigitalActive()) {
323+
int[] digitalChannels = digitalBoard.getDigitalChannels();
324+
double[] digitalSample = new double[digitalChannels.length];
325+
for (int iChan = 0; iChan < digitalChannels.length; iChan++) {
326+
digitalSample[iChan] = newData[digitalChannels[iChan]][iSample];
327+
}
328+
digitalDataAccumulationQueue.add(digitalSample);
329+
}
330+
}
331+
332+
if (currentBoard instanceof AnalogCapableBoard) {
333+
AnalogCapableBoard analogBoard = (AnalogCapableBoard) currentBoard;
334+
if (analogBoard.isAnalogActive()) {
335+
int[] analogChannels = analogBoard.getAnalogChannels();
336+
double[] analogSample = new double[analogChannels.length];
337+
for (int iChan = 0; iChan < analogChannels.length; iChan++) {
338+
analogSample[iChan] = newData[analogChannels[iChan]][iSample];
339+
}
340+
analogDataAccumulationQueue.add(analogSample);
341+
}
342+
}
290343
}
291344
}
292345

293-
public void checkIfEnoughDataToSend() {
346+
private void checkIfEnoughDataToSend() {
294347
newTimeSeriesDataToSend.set(dataAccumulationQueue.size() >= nPointsPerUpdate);
295348

296349
if (newTimeSeriesDataToSend.get()) {
@@ -321,6 +374,44 @@ class W_Networking extends Widget {
321374
markerDataBufferToSend[iSample] = markerDataAccumulationQueue.pop().floatValue();
322375
}
323376
}
377+
378+
if (currentBoard instanceof AccelerometerCapableBoard) {
379+
newAccelDataToSend.set(accelDataAccumulationQueue.size() >= nPointsPerUpdate);
380+
if (newAccelDataToSend.get()) {
381+
for (int iSample = 0; iSample < nPointsPerUpdate; iSample++) {
382+
double[] sample = accelDataAccumulationQueue.pop();
383+
384+
for (int iChan = 0; iChan < sample.length; iChan++) {
385+
accelDataBufferToSend[iChan][iSample] = (float) sample[iChan];
386+
}
387+
}
388+
}
389+
}
390+
391+
if (currentBoard instanceof BoardCyton) {
392+
newDigitalDataToSend.set(digitalDataAccumulationQueue.size() >= nPointsPerUpdate);
393+
if (newDigitalDataToSend.get()) {
394+
for (int iSample = 0; iSample < nPointsPerUpdate; iSample++) {
395+
double[] sample = digitalDataAccumulationQueue.pop();
396+
397+
for (int iChan = 0; iChan < sample.length; iChan++) {
398+
digitalDataBufferToSend[iChan][iSample] = (float) sample[iChan];
399+
}
400+
}
401+
}
402+
403+
newAnalogDataToSend.set(analogDataAccumulationQueue.size() >= nPointsPerUpdate);
404+
if (newAnalogDataToSend.get()) {
405+
for (int iSample = 0; iSample < nPointsPerUpdate; iSample++) {
406+
double[] sample = analogDataAccumulationQueue.pop();
407+
408+
for (int iChan = 0; iChan < sample.length; iChan++) {
409+
analogDataBufferToSend[iChan][iSample] = (float) sample[iChan];
410+
}
411+
}
412+
}
413+
}
414+
324415
}
325416

326417
private Boolean textfieldsAreActive(String[] names) {
@@ -1878,58 +1969,87 @@ class Stream extends Thread {
18781969
}
18791970

18801971
private void sendDigitalReadData() {
1972+
18811973
final int NUM_DIGITAL_READS = w_digitalRead.getNumDigitalReads();
18821974

18831975
if (this.protocol.equals("OSC")) {
1976+
18841977
for (int i = 0; i < NUM_DIGITAL_READS; i++) {
18851978
msg.clearArguments();
18861979
msg.setAddrPattern(baseOscAddress + "/digital/" + i);
1887-
msg.add(w_digitalRead.digitalReadDots[i].getDigitalReadVal());
1980+
//msg.add(w_digitalRead.digitalReadDots[i].getDigitalReadVal());
1981+
for (int j = 0; j < w_networking.digitalDataBufferToSend[i].length; j++) {
1982+
msg.add(w_networking.digitalDataBufferToSend[i][j]);
1983+
}
18881984
try {
18891985
this.osc.send(msg, this.oscNetAddress);
18901986
} catch (Exception e) {
18911987
println(e.getMessage());
18921988
}
18931989
}
1990+
18941991
} else if (this.protocol.equals("UDP")) {
1895-
String outputter = "{\"type\":\"digital\",\"data\":[";
1992+
1993+
StringBuilder output = new StringBuilder();
1994+
output.append("{\"type\":\"digital\",\"data\":[");
1995+
18961996
for (int i = 0; i < NUM_DIGITAL_READS; i++) {
1897-
int auxData = w_digitalRead.digitalReadDots[i].getDigitalReadVal();
1898-
String auxData_formatted = String.format("%d", auxData);
1899-
outputter += auxData_formatted;
1900-
if (i != NUM_DIGITAL_READS - 1) {
1901-
outputter += ",";
1902-
} else {
1903-
outputter += "]}\r\n";
1997+
output.append("[");
1998+
for (int j = 0; j < w_networking.digitalDataBufferToSend[i].length; j++) {
1999+
double digitalData = w_networking.digitalDataBufferToSend[i][j];
2000+
String digitalDataFormatted = String.format("%d", digitalData);
2001+
output.append(digitalDataFormatted);
2002+
if (j != w_networking.digitalDataBufferToSend[i].length - 1) {
2003+
output.append(",");
2004+
}
19042005
}
2006+
String channelArrayEnding = i != NUM_DIGITAL_READS - 1 ? "]," : "]";
2007+
output.append(channelArrayEnding);
19052008
}
2009+
2010+
output.append("]}\r\n");
2011+
19062012
try {
1907-
this.udp.send(outputter, this.ip, this.port);
2013+
this.udp.send(output.toString(), this.ip, this.port);
19082014
} catch (Exception e) {
19092015
println(e.getMessage());
19102016
}
2017+
19112018
} else if (this.protocol.equals("LSL")) {
1912-
for (int i = 0; i < NUM_DIGITAL_READS; i++) {
1913-
dataToSend[i] = w_digitalRead.digitalReadDots[i].getDigitalReadVal();
2019+
2020+
int numChannels = NUM_DIGITAL_READS;
2021+
int numSamples = w_networking.digitalDataBufferToSend[0].length;
2022+
float[] _dataToSend = new float[numChannels * numSamples];
2023+
for (int sample = 0; sample < numSamples; sample++) {
2024+
for (int channel = 0; channel < numChannels; channel++) {
2025+
_dataToSend[channel + sample * numChannels] = w_networking.digitalDataBufferToSend[channel][sample];
2026+
}
19142027
}
1915-
outlet_data.push_sample(dataToSend);
2028+
outlet_data.push_sample(_dataToSend);
2029+
19162030
} else if (this.protocol.equals("Serial")) {
1917-
// Data Format: 0,1,0,1,0\n or 0,1,0\n depending if WiFi Shield is used
1918-
// 2 chars per pin, including \n char last pin
1919-
serialMessage = "";
2031+
2032+
StringBuilder serialMessage = new StringBuilder();
2033+
19202034
for (int i = 0; i < NUM_DIGITAL_READS; i++) {
1921-
int auxData = w_digitalRead.digitalReadDots[i].getDigitalReadVal();
1922-
String auxData_formatted = String.format("%d", auxData);
1923-
serialMessage += auxData_formatted;
1924-
if (i != NUM_DIGITAL_READS - 1) {
1925-
serialMessage += ",";
1926-
} else {
1927-
serialMessage += "\n";
2035+
serialMessage.append("[");
2036+
for (int j = 0; j < w_networking.digitalDataBufferToSend[i].length; j++) {
2037+
double digitalData = w_networking.digitalDataBufferToSend[i][j];
2038+
String digitalDataFormatted = String.format("%d", digitalData);
2039+
serialMessage.append(digitalDataFormatted);
2040+
if (j != w_networking.digitalDataBufferToSend[i].length - 1) {
2041+
serialMessage.append(",");
2042+
}
19282043
}
2044+
String channelArrayEnding = i != NUM_DIGITAL_READS - 1 ? "]," : "]";
2045+
serialMessage.append(channelArrayEnding.toString());
19292046
}
2047+
2048+
serialMessage.append("\n");
2049+
19302050
try {
19312051
// println(serialMessage);
1932-
this.serial_networking.write(serialMessage);
2052+
this.serial_networking.write(serialMessage.toString());
19332053
} catch (Exception e) {
19342054
println(e.getMessage());
19352055
}

0 commit comments

Comments
 (0)