MNE-CPP  beta 1.0
tmsidriver.cpp
Go to the documentation of this file.
1 //=============================================================================================================
37 //*************************************************************************************************************
38 //=============================================================================================================
39 // INCLUDES
40 //=============================================================================================================
41 
42 #include "tmsidriver.h"
43 #include "tmsiproducer.h"
44 
45 
46 //*************************************************************************************************************
47 //=============================================================================================================
48 // USED NAMESPACES
49 //=============================================================================================================
50 
51 using namespace TMSIPlugin;
52 
53 
54 //*************************************************************************************************************
55 //=============================================================================================================
56 // DEFINE MEMBER METHODS
57 //=============================================================================================================
58 
60 : m_pTMSIProducer(pTMSIProducer)
61 , m_bDllLoaded(true)
62 , m_bInitDeviceSuccess(false)
63 , m_uiNumberOfChannels(138)
64 , m_uiSamplingFrequency(1024)
65 , m_uiSamplesPerBlock(1)
66 , m_bUseChExponent(false)
67 , m_bUseUnitGain(false)
68 , m_bUseUnitOffset(false)
69 , m_bWriteDriverDebugToFile(false)
70 , m_sOutputFilePath("/mne_x_plugins/resources/tmsi")
71 , m_bUseCommonAverage(false)
72 , m_bMeasureImpedances(false)
73 {
74  //Initialise NULL pointers
75  m_oLibHandle = NULL ;
76  m_HandleMaster = NULL;
77  m_PSPDPMasterDevicePath = NULL;
78  m_lSignalBuffer = NULL;
79 
80  //Open library
81 // TCHAR Path[MAX_PATH];
82 // GetSystemDirectory(Path, sizeof(Path) / sizeof(TCHAR) );
83 // lstrcat(Path, _T("\\TMSiSDK.dll"));
84 // m_oLibHandle = LoadLibrary(Path);
85 
86  //Check which driver dll to take: TMSiSDK.dll oder TMSiSDK32bit.dll
87 // if(TMSISDK)
88 #ifdef TAKE_TMSISDK_DLL //32 bit system & 64 bit (with 64 bit compiler)
89  m_oLibHandle = ::LoadLibrary(L"C:\\Windows\\System32\\TMSiSDK.dll");
90 #elif TAKE_TMSISDK_32_DLL //64 bit (with 32 bit compiler)
91 // if(TMSISDK32)
92  m_oLibHandle = ::LoadLibrary(L"C:\\Windows\\SysWOW64\\TMSiSDK32bit.dll");
93 #endif
94 
95  //If dll can't be open return
96  if( m_oLibHandle == NULL)
97  {
98  cout << "Plugin TMSI - ERROR - Couldn't load DLL - Check if the driver for the TMSi USB Fiber Connector installed in the system dir" << endl;
99  m_bDllLoaded = false;
100  return;
101  }
102 
103  //Load DLL methods for initializing the driver
104  __load_dll_func__(m_oFpOpen, POPEN, "Open");
105  __load_dll_func__(m_oFpClose, PCLOSE, "Close");
106  __load_dll_func__(m_oFpStart, PSTART, "Start");
107  __load_dll_func__(m_oFpStop, PSTOP, "Stop");
108  __load_dll_func__(m_oFpGetSignalFormat, PGETSIGNALFORMAT, "GetSignalFormat");
109  __load_dll_func__(m_oFpSetSignalBuffer, PSETSIGNALBUFFER, "SetSignalBuffer");
110  __load_dll_func__(m_oFpGetSamples, PGETSAMPLES, "GetSamples");
111  __load_dll_func__(m_oFpGetBufferInfo, PGETBUFFERINFO, "GetBufferInfo");
112  __load_dll_func__(m_oFpFree, PFREE, "Free");
113  __load_dll_func__(m_oFpLibraryInit, PLIBRARYINIT, "LibraryInit");
114  __load_dll_func__(m_oFpLibraryExit, PLIBRARYEXIT, "LibraryExit");
115  __load_dll_func__(m_oFpGetDeviceList, PGETDEVICELIST, "GetDeviceList");
116  __load_dll_func__(m_oFpGetFrontEndInfo, PGETFRONTENDINFO, "GetFrontEndInfo");
117  __load_dll_func__(m_oFpSetRefCalculation, PSETREFCALCULATION, "SetRefCalculation");
118  __load_dll_func__(m_oFpSetMeasuringMode, PSETMEASURINGMODE, "SetMeasuringMode");
119  __load_dll_func__(m_oFpGetErrorCode, PGETERRORCODE, "GetErrorCode");
120 
121  cout << "Plugin TMSI - INFO - TMSIDriver() - Successfully loaded all DLL functions" << endl;
122 }
123 
124 
125 //*************************************************************************************************************
126 
128 {
129  //cout << "TMSIDriver::~TMSIDriver()" << endl;
130 }
131 
132 
133 //*************************************************************************************************************
134 
135 bool TMSIDriver::initDevice(int iNumberOfChannels,
136  int iSamplingFrequency,
137  int iSamplesPerBlock,
138  bool bUseChExponent,
139  bool bUseUnitGain,
140  bool bUseUnitOffset,
141  bool bWriteDriverDebugToFile,
142  QString sOutpuFilePath,
143  bool bUseCommonAverage,
144  bool bMeasureImpedance)
145 {
146  //Check if the driver DLL was loaded
147  if(!m_bDllLoaded)
148  return false;
149 
150  //Set global variables
151  m_uiNumberOfChannels = iNumberOfChannels;
152  m_uiSamplingFrequency = iSamplingFrequency;
153  m_uiSamplesPerBlock = iSamplesPerBlock;
154  m_bUseChExponent = bUseChExponent;
155  m_bUseUnitGain = bUseUnitGain;
156  m_bUseUnitOffset = bUseUnitOffset;
157  m_bWriteDriverDebugToFile = bWriteDriverDebugToFile;
158  m_sOutputFilePath = sOutpuFilePath;
159  m_bUseCommonAverage = bUseCommonAverage;
160  m_bMeasureImpedances = bMeasureImpedance;
161 
162  //Open file to write to
163  if(m_bWriteDriverDebugToFile)
164  m_outputFileStream.open("mne_x_plugins/resources/tmsi/TMSi_Driver_Debug.txt", ios::trunc); //ios::trunc deletes old file data
165 
166  //Check if device handler already exists and a connection was established before
167 // if(m_HandleMaster != NULL)
168 // {
169 // m_oFpClose(m_HandleMaster);
170 // m_HandleMaster = NULL;
171 // }
172  int ErrorCode = 0;
173  m_HandleMaster = m_oFpLibraryInit(TMSiConnectionUSB, &ErrorCode);
174 
175  if( ErrorCode != 0 )
176  {
177  cout << "Plugin TMSI - ERROR - initDevice() - Can not initialize library" << endl;
178  return false;
179  }
180 
181  //Get the device list of connected devices
182  char **DeviceList = NULL;
183  int NrOfDevices=0;
184 
185  DeviceList = m_oFpGetDeviceList(m_HandleMaster, &NrOfDevices);
186 
187  if( NrOfDevices == 0 )
188  {
189  cout << "Plugin TMSI - ERROR - initDevice() - Frontend list NOT available - Maybe no devices are connected" << endl;
190  m_oFpLibraryExit(m_HandleMaster);
191  return false;
192  }
193 
194  //Open device
195  BOOLEAN Status;
196  char *DeviceLocator = DeviceList[0] ;
197  Status = m_oFpOpen(m_HandleMaster, DeviceLocator);
198 
199  //Stop the device from sampling. Just in case the device was not stopped correctly after the last sampling process
200  m_oFpStop(m_HandleMaster);
201 
202  if(!Status)
203  {
204  cout << "Plugin TMSI - ERROR - initDevice() - Failed to open connected device" << endl;
205  m_oFpLibraryExit(m_HandleMaster);
206  return false;
207  }
208 
209  // Turn on the impendance mode
210  ULONG impedanceMode = 3;
211  ULONG normalMode = 0;
212 
213  if(m_bMeasureImpedances)
214  {
215  if(m_oFpSetMeasuringMode(m_HandleMaster, impedanceMode, 1))
216  cout << "Plugin TMSI - INFO - Now measuring impedances" << endl;
217  else
218  {
219  int ErrorCode = m_oFpGetErrorCode(m_HandleMaster);
220  cout << "Unable to set Measuremode impedance, errorcode = " << ErrorCode << endl;
221  }
222  }
223  else
224  m_oFpSetMeasuringMode(m_HandleMaster, normalMode, 0);
225 
226  //Get information about the connected device
227  FRONTENDINFO FrontEndInfo;
228  Status = m_oFpGetFrontEndInfo(m_HandleMaster, &FrontEndInfo);
229  unsigned short serial, hwVersion, swVersion, baseSf, maxRS232, nrOfChannels;
230 
231  if(!Status)
232  cout << "Plugin TMSI - ERROR - initDevice() - FrontendInfo NOT available" << endl;
233  else
234  {
235  serial = FrontEndInfo.Serial;
236  hwVersion = FrontEndInfo.HwVersion;
237  swVersion = FrontEndInfo.SwVersion;
238  baseSf = FrontEndInfo.BaseSf;
239  maxRS232 = FrontEndInfo.maxRS232;
240  nrOfChannels = FrontEndInfo.NrOfChannels;
241  }
242 
243  // Set Ref Calculation
244  if(m_bUseCommonAverage)
245  {
246  BOOLEAN setRefCalculation = m_oFpSetRefCalculation(m_HandleMaster, 1);
247  if(setRefCalculation)
248  cout << "Plugin TMSI - INFO - initDevice() - Common average now active" << endl;
249  else
250  cout << "Plugin TMSI - INFO - initDevice() - Common average is inactive (Could not be initiated)" << endl;
251  }
252 
253  //Get information about the signal format created by the device - UnitExponent, UnitGain, UnitOffSet
254  PSIGNAL_FORMAT pSignalFormat = m_oFpGetSignalFormat(m_HandleMaster, NULL);
255 
256  if(pSignalFormat != NULL)
257  {
258  wcscpy_s(m_wcDeviceName, pSignalFormat->PortName);
259  m_ulSerialNumber = pSignalFormat->SerialNumber;
260  m_uiNumberOfAvailableChannels = pSignalFormat[0].Elements;
261 
262  if(m_bWriteDriverDebugToFile)
263  m_outputFileStream << "Found "<< m_wcDeviceName << " device (" << m_ulSerialNumber << ") with " << m_uiNumberOfAvailableChannels << " available channels" << endl << endl;
264 
265  for(uint i = 0 ; i < m_uiNumberOfAvailableChannels; i++ )
266  {
267  m_vExponentChannel.push_back(pSignalFormat[i].UnitExponent);
268  m_vUnitGain.push_back(pSignalFormat[i].UnitGain);
269  m_vUnitOffSet.push_back(pSignalFormat[i].UnitOffSet);
270 
271  if(m_bWriteDriverDebugToFile)
272  m_outputFileStream << "Channel number: " << i << " has type " << pSignalFormat[i].Type << " , format " << pSignalFormat[i].Format << " exponent " << pSignalFormat[i].UnitExponent << " gain " << pSignalFormat[i].UnitGain << " offset " << pSignalFormat[i].UnitOffSet << endl;
273  }
274 
275  if(m_bWriteDriverDebugToFile)
276  m_outputFileStream << endl;
277  }
278 
279  //Initialise and set up (sample rate/frequency and buffer size) the internal driver signal buffer which is used by the driver to store the value
280  ULONG iSamplingFrequencyMilliHertz = m_uiSamplingFrequency*1000; //Times 1000 because the driver works in millihertz
281  ULONG iBufferSize = MAX_BUFFER_SIZE; //see TMSi doc file for more info. This size is not defined in bytes but in the number of elements which are to be sampled. A sample in this case is one conversion result for all input channels..
282 
283  if(!m_oFpSetSignalBuffer(m_HandleMaster, &iSamplingFrequencyMilliHertz, &iBufferSize))
284  {
285  cout << "Plugin TMSI - ERROR - initDevice() - Failed to allocate signal buffer" << endl;
286  m_oFpLibraryExit(m_HandleMaster);
287  return false;
288  }
289 
290  //Start the sampling process
291  bool start = m_oFpStart(m_HandleMaster);
292  if(!start)
293  {
294  cout << "Plugin TMSI - ERROR - initDevice() - Failed to start the sampling procedure" << endl;
295  m_oFpLibraryExit(m_HandleMaster);
296  return false;
297  }
298 
299  //Create the buffers
300  //The sampling frequency is not needed here because it is only used to specify the internal buffer size used by the driver with setSignalBuffer()
301  m_lSignalBufferSize = m_uiSamplesPerBlock*m_uiNumberOfAvailableChannels*4;
302  m_lSignalBuffer = new LONG[m_lSignalBufferSize];
303 
304  cout << "Plugin TMSI - INFO - initDevice() - The device has been connected and initialised successfully" << endl;
305  m_bInitDeviceSuccess = true;
306  return true;
307 }
308 
309 
310 //*************************************************************************************************************
311 
313 {
314  //Clear the buffer which is used to store the received samples
315  m_vSampleBlockBuffer.clear();
316 
317  //Check if the device was initialised
318  if(!m_bInitDeviceSuccess)
319  {
320  cout << "Plugin TMSI - ERROR - uninitDevice() - Device was not initialised - therefore can not be uninitialised" << endl;
321  return false;
322  }
323 
324  //Check if the driver DLL was loaded
325  if(!m_bDllLoaded)
326  {
327  cout << "Plugin TMSI - ERROR - uninitDevice() - Driver DLL was not loaded" << endl;
328  return false;
329  }
330 
331  //Close the output stream/file
332  if(m_outputFileStream.is_open() && m_bWriteDriverDebugToFile)
333  {
334  m_outputFileStream.close();
335  m_outputFileStream.clear();
336  }
337 
338  if(!m_oFpStop(m_HandleMaster))
339  {
340  cout << "Plugin TMSI - ERROR - uninitDevice() - Failed to stop the device" << endl;
341  return false;
342  }
343 
344  if(!m_oFpClose(m_HandleMaster))
345  {
346  cout << "Plugin TMSI - ERROR - uninitDevice() - Failed to close the device" << endl;
347  return false;
348  }
349 
350  m_oFpLibraryExit(m_HandleMaster);
351 
352  //Reset to NULL pointers
353  m_oLibHandle = NULL ;
354  m_HandleMaster = NULL;
355  m_PSPDPMasterDevicePath = NULL;
356  m_lSignalBuffer = NULL;
357 
358  cout << "Plugin TMSI - INFO - uninitDevice() - Successfully uninitialised the device" << endl;
359  return true;
360 }
361 
362 
363 //*************************************************************************************************************
364 
365  bool TMSIDriver::getSampleMatrixValue(MatrixXf& sampleMatrix)
366 {
367  //Check if the driver DLL was loaded
368  if(!m_bDllLoaded)
369  return false;
370 
371  //Check if device was initialised and connected correctly
372  if(!m_bInitDeviceSuccess)
373  {
374  cout << "Plugin TMSI - ERROR - getSampleMatrixValue() - Cannot start to get samples from device because device was not initialised correctly" << endl;
375  return false;
376  }
377 
378  sampleMatrix.setZero(); // Clear matrix - set all elements to zero
379  uint iSamplesWrittenToMatrix = 0;
380  int channelMax = 0;
381  int sampleMax = 0;
382  int sampleIterator = 0;
383 
384  //get samples from device until the complete matrix is filled, i.e. the samples per block size is met
385  while(iSamplesWrittenToMatrix < m_uiSamplesPerBlock)
386  {
387  //Get sample block from device
388  LONG ulSizeSamples = m_oFpGetSamples(m_HandleMaster, (PULONG)m_lSignalBuffer, m_lSignalBufferSize);
389  LONG ulNumSamplesReceived = ulSizeSamples/(m_uiNumberOfAvailableChannels*4);
390 
391  //Only do the next steps if there was at least one sample received, otherwise skip and wait until at least one sample was received
392  if(ulNumSamplesReceived > 0)
393  {
394  int actualSamplesWritten = 0; //Holds the number of samples which are actually written to the matrix in this while procedure
395 
396  //Write the received samples to an extra buffer, so that they are not getting lost if too many samples were received. These are then written to the next matrix (block)
397  for(int i=0; i<ulNumSamplesReceived; i++)
398  {
399  for(uint j=i*m_uiNumberOfAvailableChannels; j<(i*m_uiNumberOfAvailableChannels)+m_uiNumberOfChannels; j++)
400  m_vSampleBlockBuffer.push_back((double)m_lSignalBuffer[j]);
401  }
402 
403  //If the number of available channels is smaller than the number defined by the user -> set the channelMax to the smaller number
404  if(m_uiNumberOfAvailableChannels < m_uiNumberOfChannels)
405  channelMax = m_uiNumberOfAvailableChannels;
406  else
407  channelMax = m_uiNumberOfChannels;
408 
409  //If the number of the samples which were already written to the matrix plus the last received number of samples is larger then the defined block size
410  //-> only fill until the matrix is completeley filled with samples. The other (unused) samples are still stored in the vector buffer m_vSampleBlockBuffer and will be used in the next matrix which is to be sent to the circular buffer
411  if(iSamplesWrittenToMatrix + ulNumSamplesReceived > m_uiSamplesPerBlock)
412  sampleMax = m_uiSamplesPerBlock - iSamplesWrittenToMatrix + sampleIterator;
413  else
414  sampleMax = ulNumSamplesReceived + sampleIterator;
415 
416  //Read the needed number of samples from the vector buffer to store them in the matrix
417  for(; sampleIterator < sampleMax; sampleIterator++)
418  {
419  for(int channelIterator = 0; channelIterator < channelMax; channelIterator++)
420  {
421  sampleMatrix(channelIterator, sampleIterator) = ((m_vSampleBlockBuffer.first() * (m_bUseUnitGain ? m_vUnitGain[channelIterator] : 1)) + (m_bUseUnitOffset ? m_vUnitOffSet[channelIterator] : 0)) * (m_bUseChExponent ? pow(10., (double)m_vExponentChannel[channelIterator]) : 1);
422  m_vSampleBlockBuffer.pop_front();
423  }
424 
425  actualSamplesWritten ++;
426  }
427 
428  iSamplesWrittenToMatrix = iSamplesWrittenToMatrix + actualSamplesWritten;
429  }
430 
431  if(m_outputFileStream.is_open() && m_bWriteDriverDebugToFile)
432  {
433  m_outputFileStream << "samples in buffer: " << m_vSampleBlockBuffer.size()/m_uiNumberOfChannels << endl;
434  m_outputFileStream << "ulSizeSamples: " << ulSizeSamples << endl;
435  m_outputFileStream << "ulNumSamplesReceived: " << ulNumSamplesReceived << endl;
436  m_outputFileStream << "sampleMax: " << sampleMax << endl;
437  m_outputFileStream << "sampleIterator: " << sampleIterator << endl;
438  m_outputFileStream << "iSamplesWrittenToMatrix: " << iSamplesWrittenToMatrix << endl << endl;
439  }
440  }
441 
442  if(/*m_outputFileStream.is_open() &&*/ m_bWriteDriverDebugToFile)
443  {
444  //Get device buffer info
445  ULONG ulOverflow;
446  ULONG ulPercentFull;
447  m_oFpGetBufferInfo(m_HandleMaster, &ulOverflow, &ulPercentFull);
448 
449  m_outputFileStream << "Unit offset: " << endl;
450  for(int w = 0; w<<m_vUnitOffSet.size(); w++)
451  cout << float(m_vUnitOffSet[w]) << " ";
452  m_outputFileStream << endl << endl;
453 
454  m_outputFileStream << "Unit gain: " << endl;
455  for(int w = 0; w<<m_vUnitGain.size(); w++)
456  m_outputFileStream << float(m_vUnitGain[w]) << " ";
457  m_outputFileStream << endl << endl;
458 
459  m_outputFileStream << "----------<See output file for sample matrix>----------" <<endl<<endl;
460  m_outputFileStream << "----------<Internal driver buffer is "<<ulPercentFull<<" full>----------"<<endl;
461  m_outputFileStream << "----------<Internal driver overflow is "<<ulOverflow<< ">----------"<<endl;
462  }
463 
464  return true;
465 }
466 
The EEGProducer class provides a EEG data producer for a given sampling rate.
Definition: tmsiproducer.h:89
bool initDevice(int iNumberOfChannels, int iSamplingFrequency, int iSamplesPerBlock, bool bUseChExponent, bool bUseUnitGain, bool bUseUnitOffset, bool bWriteDriverDebugToFile, QString sOutpuFilePath, bool bUseCommonAverage, bool bMeasureImpedance)
Definition: tmsidriver.cpp:135
bool getSampleMatrixValue(MatrixXf &sampleMatrix)
Definition: tmsidriver.cpp:365
Contains the declaration of the tmsidriver class. This class implements the basic communication betwe...
TMSIDriver(TMSIProducer *pTMSIProducer)
Definition: tmsidriver.cpp:59
Contains the declaration of the TMSIProducer class.