MNE-CPP  beta 1.0
triggercontrol.cpp
Go to the documentation of this file.
1 //=============================================================================================================
37 //*************************************************************************************************************
38 //=============================================================================================================
39 // INCLUDES
40 //=============================================================================================================
41 
42 #include "triggercontrol.h"
44 
45 #include "serialport.h"
46 
47 
48 //*************************************************************************************************************
49 //=============================================================================================================
50 // QT INCLUDES
51 //=============================================================================================================
52 
53 #include <QtCore/QtPlugin>
54 #include <QtCore/qmath.h>
55 #include <QDebug>
56 
57 #include <iostream>
58 
59 
60 //*************************************************************************************************************
61 //=============================================================================================================
62 // USER DEFINES
63 //=============================================================================================================
64 
65 //#define TIMEMEAS // Zeitmessung;
66 #define BUFFERX1 // X1 determination
67 //#define TIMEMUC // Zeitmessung MUC
68 //#define ALPHA // Alpha locked stimulus
69 
70 
71 //*************************************************************************************************************
72 //=============================================================================================================
73 // USED NAMESPACES
74 //=============================================================================================================
75 
76 using namespace TriggerControlPlugin;
77 using namespace MNEX;
78 using namespace XMEASLIB;
79 
80 
81 //*************************************************************************************************************
82 //=============================================================================================================
83 // DEFINE MEMBER METHODS
84 //=============================================================================================================
85 
87 : m_pTriggerOutput(NULL)
88 , m_pSerialPort(new SerialPort) // initialize a new serial port
89 , m_iBaud(115000)
90 , m_pDataSingleChannel(new dBuffer(1024))
91 , m_iNumChs(0)
92 , m_bIsRunning(false)
93 , m_fs(1024)
94 , m_dt(1/m_fs)
95 , m_refFreq(0.5)
96 , m_alphaFreq(0.5)
97 {
98  connect(this, &TriggerControl::sendByte, this, &TriggerControl::sendByteTo);
99 
100 
101 
102 #ifdef ALPHA
103  int size = (int) qFloor(m_fs/m_refFreq);
104  m_refSin = VectorXd(size);
105  m_vecCorr = VectorXd(size);
106  for(int i = 0; i < size; ++i)
107  m_refSin(i) = qSin(2*M_PI*m_refFreq*i*m_dt);
108 #endif
109 
110 
111 }
112 
113 
114 //*************************************************************************************************************
115 
117 {
118  if(this->isRunning())
119  stop();
120 }
121 
122 
123 //*************************************************************************************************************
124 
125 QSharedPointer<IPlugin> TriggerControl::clone() const
126 {
127  QSharedPointer<TriggerControl> pTriggerControlClone(new TriggerControl);
128  return pTriggerControlClone;
129 }
130 
131 
132 //*************************************************************************************************************
133 //=============================================================================================================
134 // Creating required display instances and set configurations
135 //=============================================================================================================
136 
138 {
139  // Beginn Zeitmessung
140  // Input
141  m_pRTMSAInput = PluginInputData<NewRealTimeMultiSampleArray>::create(this, "TriggerControlInI", "TriggerControl input data I");
142  connect(m_pRTMSAInput.data(), &PluginInputConnector::notify, this, &TriggerControl::update, Qt::DirectConnection);
143  m_inputConnectors.append(m_pRTMSAInput);
144  // Ende Zeitmessung*/
145 
146 
147  m_pRTSAInput = PluginInputData<NewRealTimeSampleArray>::create(this, "TriggerControlInII", "TriggerControl input data II");
148  connect(m_pRTSAInput.data(), &PluginInputConnector::notify, this, &TriggerControl::updateSingleChannel, Qt::DirectConnection);
149  m_inputConnectors.append(m_pRTSAInput);
150 
151 
152  // Output
153  m_pTriggerOutput = PluginOutputData<NewRealTimeSampleArray>::create(this, "DummyOut", "Dummy output data");
154  m_outputConnectors.append(m_pTriggerOutput);
155 
156  m_pTriggerOutput->data()->setName("Dummy Output");
157  m_pTriggerOutput->data()->setUnit("");
158  m_pTriggerOutput->data()->setMinValue(-200);
159  m_pTriggerOutput->data()->setMaxValue(360);
160  m_pTriggerOutput->data()->setSamplingRate(256.0/1.0);
161 
162 }
163 
164 
165 //*************************************************************************************************************
166 
168 {
169 
170 }
171 
172 
173 //*************************************************************************************************************
174 
176 {
177  m_bIsRunning = true;
178  QThread::start();
179 
180 
181 
182 // // ////////////////////////////
183 
184 // if(!m_pSerialPort->open()) // open Serial Port
185 // std::cout << "Not able to open port - test" << std::endl;
186 
187 // // ////////////////////////////
188 
189 #ifdef TIMEMUC
190 
191  if(!m_pSerialPort->open()) // open Serial Port
192  std::cout << "Not able to open port - test" << std::endl;
193 
194 #endif
195 
196 
197 
198 #ifdef TIMEMEAS
199 
200 
201 
202  // Beginn Zeitmessung
203 
204 
205 
206 
207  if(m_pSerialPort->open()) // open Serial Port
208  {
209  m_qTime.start();
210  QByteArray t_data;
211  m_pSerialPort->m_digchannel.replace(9,1); // select 1st digital channel
212  //t_data.append(0x01);
213  m_pSerialPort->encodedig(); // encode signal to m_data
214 // t_data[0] = t_data[0]|0x01;
215  m_pSerialPort->sendData(m_pSerialPort->m_data);
216 
217  m_qTime.start();
218  //m_pSerialPort->sendData(t_data);
219  std::cout << "data sent" << std::endl;
220  }
221  else
222  {
223  std::cout << "Sending not possible, please check settings" << std::endl;
224  }
225 #endif
226 
227 
228  return true;
229 }
230 
231 
232 //*************************************************************************************************************
233 
235 {
236  m_pSerialPort->close();
237 
238  m_bIsRunning = false;
239 
240  // Stop threads
241  QThread::terminate();
242  QThread::wait();
243 
244  m_pDataSingleChannel->clear();
245 
246 
247  //In case the semaphore blocks the thread -> Release the QSemaphore and let it exit from the pop function (acquire statement)
248 
249  if(m_pDataMatrixBuffer)
250  {
251  m_pDataMatrixBuffer->releaseFromPop();
252  m_pDataMatrixBuffer->clear();
253  }
254 
255 
256  //Beginn Zeitmessung
257  double sum = 0;
258  for(int i=0; i<m_vTimes.size(); i++)
259  sum += m_vTimes[i];
260 
261  QFile file(qApp->applicationDirPath()+"/mne_x_plugins/resources/triggercontrol/t_meas.txt");
262  for(int i=0; i<m_vTimes.size(); i++)
263  sum += m_vTimes[i];
264 
265  std::cout << "Average time: " << sum/m_vTimes.size() << std::endl;
266  std::cout << "Size m_vTimes: " << m_vTimes.size() << std::endl;
267 
268  file.open(QIODevice::WriteOnly | QIODevice::Text);
269  QTextStream out(&file);
270 
271  for(int i=0; i<m_vTimes.size() ;i++)
272  out << m_vTimes[i] << endl;
273 
274  // optional, as QFile destructor will already do it:
275  file.close();
276 
277  m_pData.clear();
278  m_vTimes.clear();
279 // Ende Zeitmessung
280 
281 
282  return true;
283 }
284 
285 
286 //*************************************************************************************************************
287 
289 {
290  return _IAlgorithm;
291 }
292 
293 
294 //*************************************************************************************************************
295 
296 QString TriggerControl::getName() const
297 {
298  return "Trigger Control";
299 }
300 
301 
302 //*************************************************************************************************************
303 
305 {
306  TriggerControlSetupWidget* setupWidget = new TriggerControlSetupWidget(this);//widget is later distroyed by CentralWidget - so it has to be created everytime new
307 
308  // QWidget* setupWidget = new QWidget;
309  return setupWidget;
310 }
311 
312 
313 //*************************************************************************************************************
314 
316 {
317  QSharedPointer<NewRealTimeSampleArray> pRTSA = pMeasurement.dynamicCast<NewRealTimeSampleArray>();
318  if(pRTSA)
319  {
320 // m_qMutex.lock();
321 // qint32 t_iSize = pRTSA->getArraySize();
322 // for(qint32 i = 0; i < t_iSize; ++i)
323 // m_pDataSingleChannel->push(pRTSA->getSampleArray()[i]);//Append sample wise
324 // m_qMutex.unlock();
325  }
326 }
327 
328 
329 //*************************************************************************************************************
330 
332 {
334  QSharedPointer<NewRealTimeMultiSampleArray> pRTMSA = pMeasurement.dynamicCast<NewRealTimeMultiSampleArray>();
335  if(pRTMSA)
336  {
337  //Check if buffer initialized
338  if(!m_pDataMatrixBuffer)
339  m_pDataMatrixBuffer = CircularMatrixBuffer<double>::SPtr(new CircularMatrixBuffer<double>(64, pRTMSA->getNumChannels(), pRTMSA->getMultiSampleArray()[0].cols()));
340 
341 // MatrixXd t_mat;
342 
343 // for(qint32 i = 0; i < pRTMSA->getMultiArraySize(); ++i)
344 // {
345 // t_mat = pRTMSA->getMultiSampleArray()[i];
346 // m_pDataMatrixBuffer->push(&t_mat);
347 // }
348 
351 
356  }
357  // ENDE Zeitmessung */
358 }
359 
360 
361 
362 
363 //*************************************************************************************************************
364 
365 
367 {
368 
369 
370 #ifdef ALPHA
371 
372  int periodTime = (int)qFloor(1.0/m_alphaFreq * 1000);
373  int basisDelay = 4;
374  int shift = 0;
375 
376  int channel = 132;
377  int posStim = 0;
378  int posMax = 0;
379 
380  MatrixXd t_mat;
381 
382  while(m_bIsRunning)
383  {
384 
385 // if(m_pDataMatrixBuffer)
386 // t_mat = m_pDataMatrixBuffer->pop();
387 
388 // m_qMutex.lock();
389 // if(m_pData.size() > 2 * m_refSin.size())
390 // {
391 
392 // bool stimFound = false;
393 
394 // for(int i = 0; i < 2 * m_pData.size(); ++i)
395 // {
396 // if(m_pData[i](136) > 1000) //ToDo stim is larger than one sample remove at least one more than stim duration
397 // {
398 // posStim = i;
399 // stimFound = true;
400 // }
401 // }
402 
403 
404 // if(stimFound)
405 // {
406 // stimFound = false;
407 
408 // //Correlate Vector with RefSin over one period
409 // for(int currentSample = 0; currentSample < m_refSin.size(); ++currentSample)
410 // {
411 // VectorXd b(m_refSin.size());
412 
413 // for(int i = 0; i < b.size(); ++i)
414 // b(i) = m_pData[i+currentSample](channel);
415 
416 // ++currentSample;
417 
418 // m_vecCorr(currentSample) = (corr(m_refSin, b));
419 // }
420 // m_vecCorr.maxCoeff(&posMax);
421 
422 
423 // shift = (int)((posStim - posMax) * m_dt);
424 
425 // }
426 
427 
428 // m_pData.remove(0, m_refSin.size());
429 // }
430 
431 // m_qMutex.unlock();
432 
433  msleep(periodTime-basisDelay-shift-10);
434 
435  shift = 0;
436 
437  emit sendByte(1);
438 
439  msleep(10);
440 
441  emit sendByte(0);
442 
443 
444  }
445 #endif
446 
447 
448 
449 
450 
451 #ifdef TIMEMUC
452  connect(m_pSerialPort.data(), &SerialPort::byteReceived, this, &TriggerControl::byteReceived);
453 
454 
455  m_isReceived = false;
456  emit sendByte(1);
457  m_qTime.start();
458 
459  while(m_bIsRunning)
460  {
461  if(m_isReceived)
462  {
463  m_vTimes.push_back(m_qTime.elapsed());
464  m_isReceived = false;
465  emit sendByte(1);
466  }
467  }
468 #endif
469 
470 
471 
472 #ifdef TIMEMEAS
473 
474  //Beginn Zeitmessung - alpha zeitmessung
475 
476  m_pData.clear();
477 
478 
479  bool t_bFound = false;
480  double x_u = -0.01;
481  double x_o = 0.01;
482 
483  // int count = 0;
484 
485 
486  while(m_bIsRunning)
487  {
488  m_qMutex.lock();
489 
490  if(t_bFound && m_pData.size() > 0)
491  {
492  // m_pData.clear();
493  // ++count;
494 
495  msleep(5000);
496  m_pData.clear();
497  t_bFound = false;
498 
499  /* if(count > 2)
500  {
501  t_bFound = false;
502  count = 0;
503 
504  emit sendByte(1);
505  m_qTime.start();
506  }*/
507 
508  }
509 
510  if(m_pData.size() > 0)
511  {
512  if((!t_bFound) && (m_pData.first()[m_iNumChs-2] > x_u) && (m_pData.first()[m_iNumChs-2] < x_o)) // x_u untere Schranke // x_o obere Schranke
513  {
514 
515 
516  //m_vTimes.push_back(m_qTime.elapsed());
517  emit sendByte(1);
518  msleep(10);
519  emit sendByte(0);
520  t_bFound = true;
521  }
522 
523  m_pData.pop_front();
524  }
525  m_qMutex.unlock();
526 
527  }
528  // Ende Zeitmessung alpha zeitmessung
529 
530 #endif
531 
532 #ifdef BUFFERX1
533 
534  while(m_bIsRunning)
535  {
536  emit sendByte(1, m_pSerialPort->m_wiredChannel);
537  msleep(20);
538  emit sendByte(0, m_pSerialPort->m_wiredChannel);
539  msleep(500);
540  }
541 
542 #endif
543 
544 
545 
546 
547 
548 
549 
550 
551 
552 
553 
554 
555 
556 
557 
558 
559 
560 
561 
562 
563 
564 
565 
566 // //Beginn Zeitmessung
567 
568 // m_pData.clear();
569 
570 
571 // bool t_bFound = false;
572 
573 // int count = 0;
574 
575 
576 // while(m_bIsRunning)
577 // {
578 // m_qMutex.lock();
579 
580 // if(t_bFound && m_pData.size() > 0)
581 // {
582 // m_pData.clear();
583 // ++count;
584 
585 // if(count > 2)
586 // {
587 // t_bFound = false;
588 // count = 0;
589 
590 // emit sendByte(1);
591 // m_qTime.start();
592 // }
593 
594 // }
595 
596 // if(m_pData.size() > 0)
597 // {
598 // if(!t_bFound && m_pData.first()[m_iNumChs-2] > 1000)
599 // {
600 // //std::cout << "Time elapsed: " << m_qTime.elapsed() << std::endl;
601 
602 // m_vTimes.push_back(m_qTime.elapsed());
603 // emit sendByte(0);
604 
605 // t_bFound = true;
606 // }
607 
608 // m_pData.pop_front();
609 // }
610 // m_qMutex.unlock();
611 // }
612 
613 
615 
616 // double v_old = 0;
617 
618 // while (true)
619 // {
620 // /* Dispatch the inputs */
621 // double v = m_pDataSingleChannel->pop();
622 
623 // double diff = v_old - v;
624 
625 // m_pTriggerOutput->data()->setValue(diff);
626 
627 // if(diff > 20)
628 // {
629 // //ToDo: Implement your algorithm here
630 
631 // }
632 
633 
634 
635 // v_old = v;
636 
637 
638 
639 
640 // }
641 
642 // // ////////////////////////////
643 // int count = 0;
644 // double v = 0;
645 
646 // while (true)
647 // {
648 // //ToDo: Implement your algorithm here
649 
650 // if( (count % 5 == 0) )
651 // {
652 // v = count % 2;
653 // //m_pTriggerOutput->data()->setValue(v);
654 
655 // if ( v == 1)
656 // {
657 // emit sendByte(1);
658 // // m_pSerialPort->m_digchannel.replace(0,1); // select 1st digital channel
659 // // m_pSerialPort->encodedig(); // encode signal to m_data
660 // // m_pSerialPort->sendData(m_pSerialPort->m_data);
661 
662 // }
663 // else if (v == 0)
664 // {
665 // emit sendByte(0);
666 // // m_pSerialPort->m_digchannel.replace(0,0); // select 1st digital channel
667 // // m_pSerialPort->encodedig(); // encode signal to m_data
668 // // m_pSerialPort->sendData(m_pSerialPort->m_data);
669 // }
670 
671 // }
672 
673 // msleep((1.0/256.0)*10000.0);
674 // ++count;
675 // }
676 
677 
678 }
679 
680 
681 
682 //*************************************************************************************************************
683 
684 void TriggerControl::sendByteTo(int value, int channel)
685 {
686  if (value == 0)
687  {
688  m_pSerialPort->m_digchannel.replace(channel,0); // select 1st digital channel
689  m_pSerialPort->encodedig(); // encode signal to m_data
690  m_pSerialPort->sendData(m_pSerialPort->m_data);
691  }
692  else
693  {
694  m_pSerialPort->m_digchannel.replace(channel,1); // select 1st digital channel
695  m_pSerialPort->encodedig(); // encode signal to m_data
696  m_pSerialPort->sendData(m_pSerialPort->m_data);
697  }
698 
699 }
700 
701 
702 //*************************************************************************************************************
703 
705 {
706  m_isReceived = true;
707 }
708 
709 
710 //*************************************************************************************************************
711 
712 double TriggerControl::corr(VectorXd a, VectorXd b)
713 {
714  VectorXd c = a.transpose()*b;
715 
716  return c(0)/a.size();
717 }
Contains the declaration of the TriggerControlSetupWidget class.
OutputConnectorList m_outputConnectors
Definition: IPlugin.h:222
The SerialPort is a class which holds all properties and methods necesarry to open, communicate and close a serial port. In most cases you want to open the port, encode your output information (digital, analog or retrieve) and decode input information (digital or analog). When you are done, close the serial port.
Definition: serialport.h:89
The TriggerControl is a MNE-X plugin which contains an intuitive terminal for manual configurations o...
QSharedPointer< CircularMatrixBuffer > SPtr
Contains the declaration of the SerialPort class.
void sendByteTo(int value, int channel)
void updateSingleChannel(XMEASLIB::NewMeasurement::SPtr pMeasurement)
Definition: arrow.h:75
The TriggerControlSetupWidget class provides the TriggerControlToolbox configuration window...
virtual IPlugin::PluginType getType() const
QSharedPointer< NewMeasurement > SPtr
static QSharedPointer< PluginOutputData< T > > create(IPlugin *parent, const QString &name, const QString &descr)
InputConnectorList m_inputConnectors
Definition: IPlugin.h:221
The NewRealTimeSampleArray class is the base class of every NewRealTimeSampleArray Measurement...
Contains the declaration of the TriggerControl class.
virtual QSharedPointer< IPlugin > clone() const
void update(XMEASLIB::NewMeasurement::SPtr pMeasurement)
static QSharedPointer< PluginInputData< T > > create(IPlugin *parent, const QString &name, const QString &descr)
The RealTimeMultiSampleArrayNew class is the base class of every RealTimeMultiSampleArrayNew Measurem...