CEBL  2.1
Mindset24.cpp
Go to the documentation of this file.
1 
10 #include "Mindset24.hpp"
11 #include "EEGData.hpp"
12 #include <string.h>
13 #include <sstream>
14 #include <iostream>
15 using namespace std;
16 /*****************************************************************************/
17 //constructors/destructors
18 
20 {
21  Init();
22 }
23 
24 
26 {
27  debug = false;
28  mindset_fp = -1;
29  is_open = false;
30  is_mindset = false;
31 }
32 
34 {
35  Close();
36 }
37 
38 
39 /*****************************************************************************/
40 //mindset file management
41 
42 bool Mindset24::Open(const char * filename)
43 {
44  if(filename == NULL)
45  {
46  return false;
47  }
48  strcpy(this->filename,filename);
49  mindset_fp = open(filename,O_RDWR);
50  is_open = mindset_fp >= 0;
51  CheckInquiry();
52  return is_open;
53 }
54 
55 //close mindset
57 {
58  if(is_open)
59  try{
60  SendCommand(SETSAMPLERATE,0);
61  } catch(...){}
62  if(mindset_fp >= 0)
63  close(mindset_fp);
64 }
65 
66 //is the mindset ready?
68 {
69  //if mindset isn't opened it obviously isn't ready
70  if(!is_open)
71  return false;
72  //if device isn't a mindset return false
73  if(!is_mindset)
74  return false;
75  //return status from io_hdr
76  bool status;
77  try
78  {
79  status = SendCommand(READY).io_hdr.masked_status==0;
80  }
81  catch(...)
82  {
83  status = false;
84  }
85  return status;
86 }
87 
88 /*****************************************************************************/
89 //set mindset value
90 
92 {
93 
94  SendCommand(SETSAMPLERATE,s);
95 
96 }
97 
99 {
100  //int data_bytes_length = ActualBlockSize(b);
101  //unsigned char *dataBytes = (unsigned char *)malloc(dataBytes_length);
102  SendCommand(SETBLOCKSIZE, b);
103 
104 }
105 
106 
107 /*****************************************************************************/
108 //getters:
109 
111 {
112  return GetStatus().sample_rate;
113 }
114 
116 {
117  return GetStatus().block_size;
118 }
119 
120 
121 
122 
123 
124 
125 /*****************************************************************************/
126 //Private methods
127 
128 //get status of mindset
130 {
131  MindsetReply mr = SendCommand(READSTATUS);
132  unsigned char *reply = mr.reply;
133  MindsetStatus status;
134 
135  status.sample_rate = (SampleRate) reply[0];
136  status.block_size = (BlockSize) reply[5];
137 
138  //determine num data bytes
139  static const int DeviceBufferBegin = 0x2000;
140  static const int DeviceBufferEnd = 0x9DFF;
141  unsigned short shortHead;
142  unsigned short shortTail;
143  int numBytes;
144 
145  shortHead = reply[1] << 8 | reply[2];
146  shortTail = reply[3] << 8 | reply[4];
147 
148  if (shortHead <= shortTail)
149  numBytes = shortTail - shortHead;
150  else
151  numBytes = shortTail - DeviceBufferBegin + DeviceBufferEnd - shortHead;
152 
153  status.num_data_bytes = numBytes;
154 
155  return status;
156 }
157 
158 void Mindset24::CheckInquiry()
159 {
160  if(!is_open)
161  return;
162  MindsetReply mr = SendCommand(INQUIRE, 0, 0x24);
163  unsigned char *dest = mr.reply;
164  char product[31-15+1];
165  memcpy(product,dest+16,16);product[16]='\0';
166 
167 
168  delete[] mr.reply;
169  delete[] mr.sense_buffer;
170 
171  is_mindset = strstr(product,"MINDSET") !=NULL;
172 }
173 
174 
175 std::string Mindset24::Inquiry()
176 {
177  if(!is_open)
178  return "Error - Mindset Not Opened";
179 
180  std::stringstream ss;
181  MindsetReply mr = SendCommand(INQUIRE, 0, 0x24);
182 
183  unsigned char *dest = mr.reply;
184  char vendor[15-7+1];
185  char product[31-15+1];
186  char firmware[35-31+1];
187  memcpy(product,dest+16,16);product[16]='\0';
188  memcpy(vendor,dest+8,8);vendor[8]='\0';
189  memcpy(firmware,dest+32,4);firmware[4]='\0';
190 
191  ss << "Product ID:\t\t" << product << std::endl;
192  ss << "Vendor ID:\t\t" << vendor << std::endl;
193  ss << "Firmware version:\t" << firmware << std::endl;
194  ss << "Device type:\t\t" << int(dest[0]) << std::endl;
195  ss << "Type Qualifier:\t\t" << int(dest[1]) << std::endl;
196  ss << "ANSI Version:\t\t" << int(dest[2]) << std::endl;
197  ss << "Additional Length:\t" << int(dest[4]) << std::endl;
198  ss << "Firmware Year:\t\t" << int(dest[5]);
199 
200 
201 
202  delete[] mr.reply;
203  delete[] mr.sense_buffer;
204 
205  return ss.str();
206 }
207 
208 /*****************************************************************************/
209 //reading data
210 
212 {
213  ublas::matrix<double> ret;
214  int bytes_available;
215  BlockSize bsize;
216  int bytes_per_block;
217  MindsetStatus status = GetStatus();
218 
219  bytes_available = status.num_data_bytes;
220  bsize = status.block_size;
221  bytes_per_block = ActualBlockSize(bsize);
222 
223  //TODO: WHY DOES BUFFER HABE 30000 SAMPLES IN IT SOMETIMES?
224  /*check if there is less than one block to get
225  or the buffer got corrupted*/
226  if(bytes_available < bytes_per_block || bytes_available > 30000)
227  {
228  return ret;
229  }
230 
231  //determine how many full blocks are available
232  int output_len;
233  if(bytes_per_block != 0)
234  output_len = (int)(bytes_available/bytes_per_block) * bytes_per_block;
235  else
236  throw "Error reading from mindset.";
237 
238  if(debug)
239  printf("DEBUG: inside GetAllData(), bytes_available = %d, bytes_per_block = %d, output_len = %d\n",bytes_available, bytes_per_block, output_len);
240 
241  MindsetReply mr = SendCommand(READDATA, output_len/bytes_per_block, output_len);
242 
243 
244  //don't try to create the matrix if there was an error
245  if(mr.error)
246  return ret;
247 
248  ret = (CreateEEGMatrix(mr));
249  delete[] mr.reply;
250  delete[] mr.sense_buffer;
251 
252  return ret;
253 }
254 
256 {
257  int bytes_available;
258  BlockSize bsize;
259  int bytes_per_block;
260 
261  MindsetStatus status = GetStatus();
262  bytes_available = status.num_data_bytes;
263  bsize = status.block_size;
264  bytes_per_block = ActualBlockSize(bsize);
265 
266  /* Wait until enough bytes available to fill one block */
267  while (bytes_available < bytes_per_block)
268  {
269  status = GetStatus();
270  bytes_available = status.num_data_bytes;
271  bsize = status.block_size;
272  bytes_per_block = ActualBlockSize(bsize);
273  }
274 
275  ublas::matrix<double> ret(0,0);
276  MindsetReply mr = SendCommand(READDATA, 1, bytes_per_block);
277  if(mr.error)
278  return ret;
279 
280  ret = CreateEEGMatrix(mr);
281  delete[] mr.reply;
282  delete[] mr.sense_buffer;
283 
284  return ret;
285 }
286 
287 /*****************************************************************************/
288 
289 int Mindset24::ActualBlockSize(BlockSize b)
290 {
291  switch(b)
292  {
293  case BLOCKSIZE96: return 96;
294  case BLOCKSIZE192: return 192;
295  case BLOCKSIZE384: return 384;
296  case BLOCKSIZE768: return 768;
297  }
298  return 0;
299 }
300 
301 
302 
303 ublas::matrix<double> Mindset24::CreateEEGMatrix(const MindsetReply &mr)
304 {
305  int numBytes = mr.reply_len;
306  int nsamples = numBytes / 24 / 2;
307  int chan = 0;
308  int b = 0;
309  int v = 0;
310  int sample = 0;
311  ublas::matrix<double> ret_matrix;
312  if(debug)
313  printf("DEBUG: inside CreateEEGMatrix, nsamples = %d, ret_matrix size1 = %d, reply_len = %d\n",
314  nsamples,
315  int(ret_matrix.size1()),
316  int(mr.reply_len));
317 
318  //ret_matrix.reserve(24,nsamples);
319  ret_matrix.resize(24,nsamples);
320  for (sample = 0; sample < nsamples; sample++)
321  for (chan = 0; chan < 24; chan++)
322  {
323  ret_matrix(chan, sample) = ((mr.reply[b] << 8 | mr.reply[b+1]) - 0x7000) / 363.63;
324  b += 2;
325  v++;
326  }
327  return(ret_matrix);
328 }
329 
330 
331 
332 
333 
334 
335 
336 /*****************************************************************************/
337 //SendCommand
338 //sends a command to the mindset
339 MindsetReply Mindset24::SendCommand(MindsetCommand command, int value, int bytes)
340 {
341  MindsetReply ret;
342  bool debug = false;
343  memset(&ret,0,sizeof(MindsetReply));
344  ret.error = true;
345  ret.reply_len = bytes;
346  if(!is_open)
347  throw("Failed to read from mindset.");
348 
349  sg_io_hdr_t io_hdr;
350 
351  static unsigned char commandBlock[6];
352  memset(&commandBlock,0,6);
353 
354  //create generic scsi io header for ioctl
355  ret.reply = new unsigned char[ret.reply_len];
356  ret.sense_buffer = new unsigned char[SENSE_BUF_LEN];
357  unsigned char *reply = ret.reply;
358  unsigned char *sense_buffer = ret.sense_buffer;
359 
360  memset(&io_hdr,0,sizeof(sg_io_hdr_t));
361  io_hdr.interface_id = 'S';
362  io_hdr.mx_sb_len = SENSE_BUF_LEN;
363  io_hdr.cmd_len = sizeof(commandBlock);
364  io_hdr.dxfer_len = bytes;
365  io_hdr.dxferp = reply;
366  io_hdr.cmdp = commandBlock;
367  io_hdr.sbp = sense_buffer;
368  io_hdr.timeout = 5000;
369 
370  //build command
371  switch(command)
372  {
373  case INQUIRE:
374  commandBlock[0] = 0x12;
375  commandBlock[4] = bytes;
376  io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
377  break;
378  case READDATA:
379  commandBlock[0] = 0xc0;
380  commandBlock[1] = 0x04;
381  commandBlock[2] = value;
382  io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
383  break;
384  case READSTATUS:
385  commandBlock[0] = 0xc0;
386  commandBlock[1] = 0x06;
387  commandBlock[4] = 0x1e;
388  io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
389  break;
390  case READY:
391  commandBlock[0] = 0x00;
392  io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
393  break;
394  case SETSAMPLERATE:
395  commandBlock[0] = 0xc0;
396  commandBlock[1] = 0x03;
397  commandBlock[2] = value; // Sample rate
398  io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
399  break;
400  case SETBLOCKSIZE:
401  commandBlock[0] = 0xc0;
402  commandBlock[1] = 0x05;
403  commandBlock[2] = value; // Block size
404  io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
405  break;
406  default:
407  printf("Mindset SCSI: Incorrect command %d sent to Mindset.\n",command);
408  }
409 
410  //write command using ioctl
411  if(ioctl(mindset_fp, SG_IO, &io_hdr) < 0)
412  {
413  throw("Mindset SCSI: ioctl error\n");
414  }
415  // now for the error processing
416  if(debug){
417  if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
418  {
419  printf("Mindset SCSI: io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK\n");
420  if (io_hdr.sb_len_wr > 0)
421  {
422  //ms_dump(sense_buffer,io_hdr.sb_len_wr,"Mindset SCSI sense data: ");
423  }
424  if (io_hdr.masked_status)
425  printf("Mindset SCSI status=0x%x\n", io_hdr.status);
426  if (io_hdr.host_status)
427  printf("Mindset SCSI host_status=0x%x\n", io_hdr.host_status);
428  if (io_hdr.driver_status)
429  printf("Mindset driver_status=0x%x\n", io_hdr.driver_status);
430  else {
431  //ms_dump(reply,REPLY_STRING_LENGTH,"Mindset SCSI reply");
432  printf("Mindst SCSI command duration=%u millisecs, resid=%d\n",
433  io_hdr.duration, io_hdr.resid);
434  }
435  }
436  }
437 
438  //save io_hdr into mindset reply
439  ret.io_hdr = io_hdr;
440 
441  //return mindset reply
442  ret.error = false;
443  return ret;
444 }