ISIS Logo
ECLAB
An EPICS support module to export potentiostat values as process variables
ECLabDriver.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2013 Science and Technology Facilities Council (STFC), GB.
3 * All rights reverved.
4 * This file is distributed subject to a Software License Agreement found
5 * in the file LICENSE.txt that is included with this distribution.
6 \*************************************************************************/
7 
10 
11 #include <stdlib.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <errno.h>
15 #include <math.h>
16 #include <exception>
17 #include <iostream>
18 #include <map>
19 #include <vector>
20 #include <fstream>
21 #include <algorithm>
22 
23 #include <epicsTypes.h>
24 #include <epicsTime.h>
25 #include <epicsThread.h>
26 #include <epicsString.h>
27 #include <epicsTimer.h>
28 #include <epicsMutex.h>
29 #include <epicsEvent.h>
30 #include <errlog.h>
31 #include <iocsh.h>
32 #include <macLib.h>
33 
34 #include "BLFunctions.h"
35 #include "ECLabInterface.h"
36 #include "ECLabDriver.h"
37 #include "ECLabParams.h"
38 
39 #include <epicsExport.h>
40 
41 static const char *driverName="ECLabDriver";
42 
43 #if 0
44 asynStatus ECLabDriver::readOctet(asynUser *pasynUser, char *value, size_t maxChars, size_t *nActual, int *eomReason)
45 {
46  int function = pasynUser->reason;
47  int status=0;
48  const char *functionName = "readOctet";
49  const char *paramName = NULL;
50  getParamName(function, &paramName);
51  std::string value_s;
52  try
53  {
54 
55  if ( value_s.size() > maxChars ) // did we read more than we have space for?
56  {
57  *nActual = maxChars;
58  if (eomReason) { *eomReason = ASYN_EOM_CNT | ASYN_EOM_END; }
59  asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
60  "%s:%s: function=%d, name=%s, value=\"%s\" (TRUNCATED from %d chars)\n",
61  driverName, functionName, function, paramName, value_s.substr(0,*nActual).c_str(), value_s.size());
62  }
63  else
64  {
65  *nActual = value_s.size();
66  if (eomReason) { *eomReason = ASYN_EOM_END; }
67  asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
68  "%s:%s: function=%d, name=%s, value=\"%s\"\n",
69  driverName, functionName, function, paramName, value_s.c_str());
70  }
71  strncpy(value, value_s.c_str(), maxChars); // maxChars will NULL pad if possible, change to *nActual if we do not want this
72  return asynSuccess;
73  }
74  catch(const std::exception& ex)
75  {
76  epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
77  "%s:%s: status=%d, function=%d, name=%s, value=\"%s\", error=%s",
78  driverName, functionName, status, function, paramName, value_s.c_str(), ex.what());
79  *nActual = 0;
80  if (eomReason) { *eomReason = ASYN_EOM_END; }
81  value[0] = '\0';
82  return asynError;
83  }
84 }
85 #endif
86 
87 asynStatus ECLabDriver::writeOctet(asynUser *pasynUser, const char *value, size_t maxChars, size_t *nActual)
88 {
89  static const std::string ecc_dir = macEnvExpand("$(ECLAB)/ecc/");
90  int function = pasynUser->reason;
91  asynStatus status = asynSuccess;
92  const char *paramName = NULL;
93  getParamName(function, &paramName);
94  const char* functionName = "writeOctet";
95  std::string value_s(value, maxChars);
96  int addr = 0;
97  getAddress(pasynUser, &addr);
98  try
99  {
100  if (function == P_loadTech || function == P_defineTech) // addr is channel number
101  {
102  char* valueCopy = strdup(value_s.c_str()); // as strtok modfies the string
103  char *tok_save = NULL;
104  char * tech = epicsStrtok_r(valueCopy, " ,;", &tok_save); //epics vers of strtok
105  m_techniques.clear();
106  std::map<std::string,int> tech_count;
107  while (tech != NULL)
108  {
109  if (tech_count.find(tech) == tech_count.end())
110  {
111  tech_count[tech] = 0;
112  }
113  m_techniques.push_back(techinfo(tech, tech_count[tech]));
114  ++tech_count[tech];
115  tech = epicsStrtok_r(NULL, " ,;", &tok_save);
116  }
117  free(valueCopy);
118  }
119  if (function == P_loadTech)
120  {
121  TEccParams_t params;
122  for (int i = 0; i < m_techniques.size(); ++i)
123  {
124  bool first = ( i == 0 );
125  bool last = ( i == (m_techniques.size() - 1) );
126  std::vector<TEccParam_t> values;
127  getTechniqueParams(m_techniques[i].name, m_techniques[i].index, values, false);
128  if (values.size() > 0)
129  {
130  params.pParams = &(values[0]);
131  }
132  else
133  {
134  params.pParams = NULL;
135  }
136  params.len = values.size();
137  std::string ecc_file = ecc_dir + m_techniques[i].name + "4.ecc";
138  std::replace(ecc_file.begin(), ecc_file.end(), '/', '\\');
139  ECLabInterface::LoadTechnique(m_ID, addr, const_cast<char*>(ecc_file.c_str()), params, first, last, false);
140  }
141  }
142  asynPortDriver::writeOctet(pasynUser, value, maxChars, nActual);
143  asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
144  "%s:%s: function=%d, name=%s, value=%s\n",
145  driverName, functionName, function, paramName, value_s.c_str());
146  *nActual = value_s.size();
147  return asynSuccess;
148  }
149  catch(const std::exception& ex)
150  {
151  epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
152  "%s:%s: status=%d, function=%d, name=%s, value=%s, error=%s",
153  driverName, functionName, status, function, paramName, value_s.c_str(), ex.what());
154  *nActual = 0;
155  return asynError;
156  }
157 }
158 
159 asynStatus ECLabDriver::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
160 {
161  int function = pasynUser->reason;
162  asynStatus status = asynSuccess;
163  const char *paramName = NULL;
164  getParamName(function, &paramName);
165  const char* functionName = "writeFloat64";
166  int addr = 0; // channel number
167  getAddress(pasynUser, &addr);
168  try
169  {
170  setECSingleParam(this, addr, function, value); // need to include addr at some point
171  asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
172  "%s:%s: function=%d, name=%s, value=%f\n",
173  driverName, functionName, function, paramName, value);
174  return asynSuccess;
175 
176  }
177  catch(const std::exception& ex)
178  {
179  epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
180  "%s:%s: status=%d, function=%d, name=%s, value=%f, error=%s",
181  driverName, functionName, status, function, paramName, value, ex.what());
182  return asynError;
183  }
184 }
185 
186 asynStatus ECLabDriver::writeInt32(asynUser *pasynUser, epicsInt32 value)
187 {
188  static const std::string ecc_dir = macEnvExpand("$(ECLAB)/ecc/");
189  int function = pasynUser->reason;
190  asynStatus status = asynSuccess;
191  const char *paramName = NULL;
192  getParamName(function, &paramName);
193  const char* functionName = "writeInt32";
194  int addr = 0; // channel number
195  getAddress(pasynUser, &addr);
196 
197  try
198  {
199  if (function == P_startChannel)
200  {
202  }
203  else if (function == P_stopChannel)
204  {
206 // TExperimentInfos_t TExpInfos;
207 // ECLabInterface::GetExperimentInfos(m_ID, addr, &TExpInfos );
208 // std::cerr << "Exp info time " << TExpInfos.TimeHMS << " filename " << TExpInfos.Filename << std::endl;
209  }
210  else if (function == P_updateParams)
211  {
212  TEccParams_t params;
213  for (int i = 0; i < m_techniques.size(); ++i)
214  {
215  std::vector<TEccParam_t> values;
216  getTechniqueParams(m_techniques[i].name, m_techniques[i].index, values, true);
217  int maxupdate = 10; // can only update a maximum of 10 parameters at a time with ECLabInterface::UpdateParameters
218  for(int j=0; j<values.size(); j += maxupdate)
219  {
220  params.pParams = &(values[j]);
221  int n = values.size() - j;
222  params.len = (n > maxupdate ? maxupdate : n);
223  std::string ecc_file = ecc_dir + m_techniques[i].name + "4.ecc";
224  std::replace(ecc_file.begin(), ecc_file.end(), '/', '\\');
225  ECLabInterface::UpdateParameters(m_ID, addr, i, params, const_cast<char*>(ecc_file.c_str()));
226  }
227  }
228  }
229  else if (function == P_saveData)
230  {
231  setIntegerParam(P_saveData, value);
232  }
233  else
234  {
235  setECIntegerParam(this, addr, function, value); // need to include addr at some point
236  }
237  asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
238  "%s:%s: function=%d, name=%s, value=%d\n",
239  driverName, functionName, function, paramName, value);
240  return asynSuccess;
241 
242  }
243  catch(const std::exception& ex)
244  {
245  epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
246  "%s:%s: status=%d, function=%d, name=%s, value=%d, error=%s",
247  driverName, functionName, status, function, paramName, value, ex.what());
248  return asynError;
249  }
250 }
251 
253 void ECLabDriver::report(FILE* fp, int details)
254 {
255  fprintf(fp, "ECLabDriver report\n");
256  std::ostringstream oss;
257  printParams(oss);
258  fwrite(oss.str().c_str(), 1, oss.str().size(), fp);
259  asynPortDriver::report(fp, details);
260 }
261 
262 
267 ECLabDriver::ECLabDriver(const char *portName, const char *ip)
268  : asynPortDriver(portName,
269  16, /* maxAddr */
270  NUM_ECLAB_PARAMS + 100,
271  asynInt32Mask | asynInt32ArrayMask | asynInt8ArrayMask | asynFloat64Mask | asynFloat32ArrayMask | asynOctetMask | asynDrvUserMask, /* Interface mask */
272  asynInt32Mask | asynInt32ArrayMask | asynInt8ArrayMask | asynFloat64Mask | asynFloat32ArrayMask | asynOctetMask, /* Interrupt mask */
273  ASYN_CANBLOCK, /* asynFlags. This driver can block but it is not multi-device */
274  1, /* Autoconnect */
275  0, /* Default priority */
276  0) /* Default stack size*/
277 
278 {
279  const char *functionName = "ECLabDriver";
280  static const std::string ecc_dir = macEnvExpand("$(ECLAB)/ecc/");
281 
282  createParam(P_versionString, asynParamOctet, &P_version);
283  createParam(P_hostString, asynParamOctet, &P_host);
284  createParam(P_devCodeString,asynParamInt32, &P_devCode);
285  createParam(P_numChannelsString, asynParamInt32, &P_numChannels);
286  createParam(P_numSlotsString, asynParamInt32, &P_numSlots);
287  createParam(P_numTechString, asynParamInt32, &P_numTech);
288  createParam(P_memFilledString, asynParamInt32, &P_memFilled);
289  createParam(P_currEWEString, asynParamFloat64, &P_currEWE);
290  createParam(P_currECEString, asynParamFloat64, &P_currECE);
291  createParam(P_currIString, asynParamFloat64, &P_currI);
292  createParam(P_currTIMEString, asynParamFloat64, &P_currTIME);
293  createParam(P_currRCOMPString, asynParamFloat64, &P_currRCOMP);
294  createParam(P_currFREQString, asynParamFloat64, &P_currFREQ);
295  createParam(P_currSTATEString, asynParamInt32, &P_currSTATE);
296  createParam(P_currTimeBaseString, asynParamFloat64, &P_currTimeBase);
297  createParam(P_loadTechString, asynParamOctet, &P_loadTech);
298  createParam(P_defineTechString, asynParamOctet, &P_defineTech);
299  createParam(P_updateParamsString, asynParamInt32, &P_updateParams);
300  createParam(P_startChannelString, asynParamInt32, &P_startChannel);
301  createParam(P_stopChannelString, asynParamInt32, &P_stopChannel);
302  createParam(P_dataDoneString, asynParamInt32, &P_dataDone);
303  createParam(P_filePrefixString, asynParamOctet, &P_filePrefix);
304  createParam(P_saveDataString, asynParamInt32, &P_saveData);
305 
306  setStringParam(P_version, "unknown");
307  setStringParam(P_host, "unknown");
308  setIntegerParam(P_devCode, KBIO_DEV_UNKNOWN);
309  setIntegerParam(P_numChannels, 0);
310  setIntegerParam(P_numSlots, 0);
311  setStringParam(P_filePrefix, "eclab");
312  setIntegerParam(P_saveData, 1);
313 
314  addAllParameters(this);
315 
316  if ( !strcmp(ip, "SIM") )
317  {
318  ECLabInterface::BLSIM = true;
319  }
320 
321  char version[32];
322  unsigned ver_size = sizeof(version);
323  ECLabInterface::GetLibVersion(version, &ver_size);
324  setStringParam(P_version, version);
325  unsigned int timeout = 5;
326  ECLabInterface::Connect(const_cast<char *>(ip), timeout, &m_ID, &m_infos);
328 
329  uint8 chan = 1;
330  int res;
331  std::string kernel_file = ecc_dir + "kernel4.bin";
332  std::replace(kernel_file.begin(), kernel_file.end(), '/', '\\');
333  std::string xlx_file = ecc_dir + "Vmp_iv_0395_aa.xlx";
334  std::replace(xlx_file.begin(), xlx_file.end(), '/', '\\');
335  ECLabInterface::LoadFirmware(m_ID, &chan, &res, 1, 0, 0, kernel_file.c_str(), xlx_file.c_str());
336 
337  setStringParam(P_host, ip);
338  setIntegerParam(P_devCode, m_infos.DeviceCode);
339  setIntegerParam(P_numChannels, m_infos.NumberOfChannels);
340  setIntegerParam(P_numSlots, m_infos.NumberOfSlots);
341  // Create the thread for background tasks (not used at present, could be used for I/O intr scanning)
342  if (epicsThreadCreate("ECLabValuesTask",
343  epicsThreadPriorityMedium,
344  epicsThreadGetStackSize(epicsThreadStackMedium),
345  (EPICSTHREADFUNC)ECLabValuesTaskC, this) == 0)
346  {
347  printf("%s:%s: epicsThreadCreate failure\n", driverName, functionName);
348  return;
349  }
350  if (epicsThreadCreate("ECLabDataTask",
351  epicsThreadPriorityMedium,
352  epicsThreadGetStackSize(epicsThreadStackMedium),
353  (EPICSTHREADFUNC)ECLabDataTaskC, this) == 0)
354  {
355  printf("%s:%s: epicsThreadCreate failure\n", driverName, functionName);
356  return;
357  }
358 }
359 
362 {
363  ECLabDriver* driver = reinterpret_cast<ECLabDriver*>(arg);
364  if (NULL != driver)
365  {
366  driver->ECLabValuesTask();
367  }
368 }
369 
371 {
372  ECLabDriver* driver = reinterpret_cast<ECLabDriver*>(arg);
373  if (NULL != driver)
374  {
375  driver->ECLabDataTask();
376  }
377 }
378 
379 void ECLabDriver::updateCvals(int chan, TCurrentValues_t& cvals)
380 {
381  setIntegerParam(chan, P_memFilled, cvals.MemFilled);
382  setDoubleParam(chan, P_currEWE, cvals.Ewe);
383  setDoubleParam(chan, P_currECE, cvals.Ece);
384  setDoubleParam(chan, P_currI, cvals.I);
385  setDoubleParam(chan, P_currTIME, cvals.ElapsedTime);
386  setDoubleParam(chan, P_currRCOMP, cvals.Rcomp);
387  setDoubleParam(chan, P_currFREQ, cvals.Freq);
388  setIntegerParam(chan, P_currSTATE, cvals.State);
389  setDoubleParam(chan, P_currTimeBase, cvals.TimeBase);
390 }
391 
393 {
394  TCurrentValues_t cvals;
395  TChannelInfos_t cinfo;
396 // uint32_t len_buffer;
397 // char buffer[256];
398  while(true)
399  {
400  for(int i=0; i<m_infos.NumberOfChannels; ++i)
401  {
403  {
404  try
405  {
408  }
409  catch(const std::exception& ex)
410  {
411  errlogSevPrintf(errlogInfo, "%s", ex.what());
412  }
413 // len_buffer = sizeof(buffer);
414 // memset(buffer, 0, len_buffer);
415 // ECLabInterface::GetMessage(m_ID, i, buffer, &len_buffer);
416  lock();
417  updateCvals(i, cvals);
418  setIntegerParam(i, P_numTech, cinfo.NbOfTechniques);
419 
420 // if (len_buffer > 0)
421 // {
422 // std::cerr << buffer << std::endl;
423 // }
424  callParamCallbacks();
425  unlock();
426  }
427  }
428  epicsThreadSleep(1.0);
429  }
430 }
431 
432 double ECLabDriver::getTime(unsigned thigh, unsigned tlow, double start_time, double time_base)
433 {
434  return (((__int64)thigh << 32) + tlow) * time_base + start_time;
435 }
436 
437 void ECLabDriver::processPEISData(std::fstream& fs0, std::fstream& fs1, int nrows, int ncols, int technique_index, int process_index,
438  int loop, double start_time, double time_base, TDataBuffer_t* dbuffer)
439 {
440  unsigned* data = dbuffer->data;
441  double t;
442  float tf;
443  int idx;
444  float ewe, currI, freq, eweMod, currIMod, phaseZwe,eceMod, iceMod;
445  float phaseZce, ece;
446  if (process_index == 0)
447  {
448  if (ncols != 4)
449  {
450  std::cerr << "PEIS: incorrect number of columns in data for process 0" << std::endl;
451  return;
452  }
453  for(int i=0; i<nrows; ++i)
454  {
455  idx = i * ncols;
456  t = getTime(data[idx + 0], data[idx + 1], start_time, time_base);
457  BL_ConvertNumericIntoSingle(data[idx + 2], &ewe);
458  BL_ConvertNumericIntoSingle(data[idx + 3], &currI);
459  fs0 << t << "," << ewe << "," << currI << "\n";
460  }
461  }
462  else if (process_index == 1)
463  {
464  if (ncols != 14)
465  {
466  std::cerr << "PEIS: incorrect number of columns in data for process 1" << std::endl;
467  return;
468  }
469  for(int i=0; i<nrows; ++i)
470  {
471  idx = i * ncols;
472  BL_ConvertNumericIntoSingle(data[idx + 0], &freq);
473  BL_ConvertNumericIntoSingle(data[idx + 1], &eweMod);
474  BL_ConvertNumericIntoSingle(data[idx + 2], &currIMod);
475  BL_ConvertNumericIntoSingle(data[idx + 3], &phaseZwe);
476  BL_ConvertNumericIntoSingle(data[idx + 4], &ewe);
477  BL_ConvertNumericIntoSingle(data[idx + 5], &currI);
478  BL_ConvertNumericIntoSingle(data[idx + 7], &eceMod);
479  BL_ConvertNumericIntoSingle(data[idx + 8], &iceMod);
480  BL_ConvertNumericIntoSingle(data[idx + 9], &phaseZce);
481  BL_ConvertNumericIntoSingle(data[idx + 10], &ece);
482  BL_ConvertNumericIntoSingle(data[idx + 13], &tf);
483  fs1 << tf << "," << freq << "," << eweMod
484  << "," << currIMod << "," << phaseZwe << "," << ewe
485  << "," << currI << "," << eceMod << "," << iceMod
486  << "," << phaseZce << "," << ece << std::endl;
487  }
488  }
489 }
490 
491 void ECLabDriver::processOCVData(std::fstream& fs, int nrows, int ncols, int technique_index, int process_index,
492  int loop, double start_time, double time_base, TDataBuffer_t* dbuffer)
493 {
494  unsigned* data = dbuffer->data;
495  double t;
496  int idx, ret;
497  float ewe;
498  if (ncols != 3)
499  {
500  std::cerr << "OCV: incorrect number of columns in data" << std::endl;
501  return;
502  }
503  for(int i=0; i<nrows; ++i)
504  {
505  idx = i * ncols;
506  t = getTime(data[idx + 0], data[idx + 1], start_time, time_base);
507  ret = BL_ConvertNumericIntoSingle(data[idx + 2], &ewe);
508 // fs << loop << "," << technique_index << "," << t << "," << ewe << "\n";
509  fs << t << "," << ewe << "\n";
510  }
511 }
512 
514 {
515  TCurrentValues_t cvals;
516  TDataInfos_t dinfo;
517  TDataBuffer_t dbuffer;
518  int ndata;
519  std::fstream all_fs0[100], all_fs1[100];
520  unsigned file_index[100];
521  char filename[256];
522  char fileprefix[256];
523  char tbuff[64];
524  struct tm* pstm;
525  time_t now;
526  memset(file_index, 0, sizeof(file_index));
527  int savedata = 0;
528  while(true)
529  {
530  ndata = 0;
531  getIntegerParam(P_saveData, &savedata);
532  for(int i=0; i<m_infos.NumberOfChannels; ++i)
533  {
534  std::fstream& fs0 = all_fs0[i];
535  std::fstream& fs1 = all_fs1[i];
536  if (savedata == 0)
537  {
538  if (fs0.is_open())
539  {
540  fs0.close();
541  ++(file_index[i]);
542  }
543  if (fs1.is_open())
544  {
545  fs1.close();
546  }
547  lock();
548  setIntegerParam(i, P_dataDone, 1);
549  callParamCallbacks();
550  unlock();
551  continue;
552  }
554  {
555  try
556  {
557  ECLabInterface::GetData(m_ID, i, &dbuffer, &dinfo, &cvals);
558  }
559  catch(const std::exception& ex)
560  {
561  errlogSevPrintf(errlogInfo, "%s", ex.what());
562  }
563  lock();
564  updateCvals(i, cvals);
565  callParamCallbacks();
566  unlock();
567  time(&now);
568  pstm = localtime(&now);
569  strftime(tbuff, sizeof(tbuff), "%Y%m%dT%H%M%S", pstm);
570  if (dinfo.TechniqueID == KBIO_TECHID_OCV)
571  {
572  if ( cvals.State == KBIO_STATE_RUN && !(fs0.is_open()) )
573  {
574  getStringParam(P_filePrefix, sizeof(fileprefix), fileprefix);
575  sprintf(filename, "%s_%s_%d_0.csv", fileprefix, tbuff, i);
576  fs0.open(filename, std::ios::out);
577  fs0 << "Time,Ewe\n";
578  }
579  processOCVData(fs0, dinfo.NbRows, dinfo.NbCols, dinfo.TechniqueIndex, dinfo.ProcessIndex,
580  dinfo.loop, dinfo.StartTime, cvals.TimeBase, &dbuffer);
581  }
582  else if (dinfo.TechniqueID == KBIO_TECHID_PEIS)
583  {
584  if ( cvals.State == KBIO_STATE_RUN && !(fs0.is_open()) )
585  {
586  getStringParam(P_filePrefix, sizeof(fileprefix), fileprefix);
587  sprintf(filename, "%s_%s_%d_0.csv", fileprefix, tbuff, i);
588  fs0.open(filename, std::ios::out);
589  fs0 << "Time,Ewe,I\n";
590  sprintf(filename, "%s_%s_%d_1.csv", fileprefix, tbuff, i);
591  fs1.open(filename, std::ios::out);
592  fs1 << "Time,Freq,Mod Ewe,Mod I,Phase Zwe,Ewe,I,Mod Ece,Mod Ice,Phase Zce,Ece\n";
593  }
594  processPEISData(fs0, fs1, dinfo.NbRows, dinfo.NbCols, dinfo.TechniqueIndex, dinfo.ProcessIndex,
595  dinfo.loop, dinfo.StartTime, cvals.TimeBase, &dbuffer);
596  }
597  lock();
598  if (cvals.State == KBIO_STATE_STOP && cvals.MemFilled == 0)
599  {
600  if (fs0.is_open())
601  {
602  fs0.close();
603  ++(file_index[i]);
604  }
605  if (fs1.is_open())
606  {
607  fs1.close();
608  }
609  setIntegerParam(i, P_dataDone, 1);
610  }
611  else
612  {
613  ++ndata;
614  setIntegerParam(i, P_dataDone, 0);
615  }
616  callParamCallbacks();
617  unlock();
618  }
619  }
620  if (ndata == 0)
621  {
622  epicsThreadSleep(2.0);
623  }
624  else
625  {
626  epicsThreadSleep(0.2);
627  }
628  }
629 }
630 
631 extern "C" {
632 
636  int ECLabConfigure(const char *portName, const char *ip)
637  {
638  try
639  {
640  new ECLabDriver(portName, ip);
641  return(asynSuccess);
642  }
643  catch(const std::exception& ex)
644  {
645  errlogSevPrintf(errlogFatal, "ECLabConfigure failed: %s\n", ex.what());
646  return(asynError);
647  }
648  }
649 
650  // EPICS iocsh shell commands
651 
652  static const iocshArg initArg0 = { "portName", iocshArgString};
653  static const iocshArg initArg1 = { "ip", iocshArgString};
654  static const iocshArg * const initArgs[] = { &initArg0, &initArg1 };
655 
656  static const iocshFuncDef initFuncDef = {"ECLabConfigure", sizeof(initArgs) / sizeof(iocshArg*), initArgs};
657 
658  static void initCallFunc(const iocshArgBuf *args)
659  {
660  ECLabConfigure(args[0].sval, args[1].sval);
661  }
662 
664  static void ECLabRegister(void)
665  {
666  iocshRegister(&initFuncDef, initCallFunc);
667  }
668 
670 
671 }
EPICS Asyn port driver class.
Definition: ECLabDriver.h:17
int P_currTimeBase
Definition: ECLabDriver.h:55
void processPEISData(std::fstream &fs0, std::fstream &fs1, int nrows, int ncols, int technique_index, int process_index, int loop, double start_time, double time_base, TDataBuffer_t *dbuffer)
void processOCVData(std::fstream &fs, int nrows, int ncols, int technique_index, int process_index, int loop, double start_time, double time_base, TDataBuffer_t *dbuffer)
void ECLabDataTask()
#define P_currTIMEString
Definition: ECLabDriver.h:97
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value)
#define P_currFREQString
Definition: ECLabDriver.h:99
static void LoadFirmware(int ID, uint8 *pChannels, int *pResults, uint8 Length, bool ShowGauge, bool ForceReload, const char *BinFile, const char *XlxFile)
epicsExportRegistrar(ECLabRegister)
#define P_dataDoneString
Definition: ECLabDriver.h:104
void getTechniqueParams(const std::string &technique, int addr, std::vector< TEccParam_t > &values, bool changes_only)
static void GetChannelInfos(int ID, uint8 ch, TChannelInfos_t *pInfos)
Header for ECLabDriver class.
int P_stopChannel
Definition: ECLabDriver.h:63
#define P_saveDataString
Definition: ECLabDriver.h:109
__int64 t
#define P_currIString
Definition: ECLabDriver.h:96
static void ECLabDataTaskC(void *arg)
int P_saveData
Definition: ECLabDriver.h:61
static bool IsChannelPlugged(int ID, uint8 ch)
#define P_currSTATEString
Definition: ECLabDriver.h:100
static void GetCurrentValues(int ID, uint8 channel, TCurrentValues_t *pValues)
virtual void report(FILE *fp, int details)
EPICS driver report function for iocsh dbior command.
void updateCvals(int chan, TCurrentValues_t &cvals)
#define P_devCodeString
Definition: ECLabDriver.h:89
int P_currSTATE
Definition: ECLabDriver.h:54
#define P_memFilledString
Definition: ECLabDriver.h:93
void setECIntegerParam(asynPortDriver *driver, int addr, int id, epicsInt32 value)
Definition: ECLabParams.cpp:78
static void StartChannel(int ID, uint8 channel)
int P_dataDone
Definition: ECLabDriver.h:59
#define P_numTechString
Definition: ECLabDriver.h:92
#define P_numSlotsString
Definition: ECLabDriver.h:91
std::vector< techinfo > m_techniques
Definition: ECLabDriver.h:72
static const char * version
static void ECLabRegister(void)
Register new commands with EPICS IOC shell.
#define P_startChannelString
Definition: ECLabDriver.h:105
static void GetLibVersion(char *pVersion, unsigned int *psize)
int P_numSlots
Definition: ECLabDriver.h:45
int ECLabConfigure(const char *portName, const char *ip)
The function is registered via EClabRegister().
void addAllParameters(asynPortDriver *driver)
int P_updateParams
Definition: ECLabDriver.h:58
int P_numChannels
Definition: ECLabDriver.h:44
static void StopChannel(int ID, uint8 channel)
static void Connect(const char *address, uint8 TimeOut, int *pID, TDeviceInfos_t *pInfos)
static bool BLSIM
#define P_hostString
Definition: ECLabDriver.h:88
strncpy(pVersion, version,*psize)
#define P_currRCOMPString
Definition: ECLabDriver.h:98
#define NUM_ECLAB_PARAMS
Definition: ECLabDriver.h:85
#define P_filePrefixString
Definition: ECLabDriver.h:108
#define P_currEWEString
Definition: ECLabDriver.h:94
static const iocshFuncDef initFuncDef
static void testConnect(int ID)
static const char * driverName
Name of driver for use in message printing.
Definition: ECLabDriver.cpp:41
void printParams(std::ostream &os)
ECLabDriver(const char *portName, const char *ip)
Constructor for the ECLabDriver class.
#define P_loadTechString
Definition: ECLabDriver.h:101
#define P_currTimeBaseString
Definition: ECLabDriver.h:107
#define P_currECEString
Definition: ECLabDriver.h:95
int P_loadTech
Definition: ECLabDriver.h:56
virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value)
double getTime(unsigned thigh, unsigned tlow, double start_time, double time_base)
int P_currRCOMP
Definition: ECLabDriver.h:52
uint8 timeout
Provide an interface to EC lab functions, converting error codes into C++ exceptions.
int P_filePrefix
Definition: ECLabDriver.h:60
static void UpdateParameters(int ID, uint8 channel, int TechIndx, TEccParams_t Params, const char *EccFileName)
memset(TExpInfos, 0, sizeof(TExperimentInfos_t))
#define P_stopChannelString
Definition: ECLabDriver.h:106
static void ECLabValuesTaskC(void *arg)
int P_memFilled
Definition: ECLabDriver.h:47
pBuf data[0]
#define P_versionString
Definition: ECLabDriver.h:87
void setECSingleParam(asynPortDriver *driver, int addr, int id, epicsFloat64 value)
Definition: ECLabParams.cpp:98
static void GetData(int ID, uint8 channel, TDataBuffer_t *pBuf, TDataInfos_t *pInfos, TCurrentValues_t *pValues)
static void LoadTechnique(int ID, uint8 channel, char *pFName, TEccParams_t Params, bool FirstTechnique, bool LastTechnique, bool DisplayParams)
#define P_updateParamsString
Definition: ECLabDriver.h:103
void ECLabValuesTask()
static void initCallFunc(const iocshArgBuf *args)
int P_startChannel
Definition: ECLabDriver.h:62
#define P_numChannelsString
Definition: ECLabDriver.h:90
int P_currFREQ
Definition: ECLabDriver.h:53
int P_defineTech
Definition: ECLabDriver.h:57
TDeviceInfos_t m_infos
Definition: ECLabDriver.h:65
#define P_defineTechString
Definition: ECLabDriver.h:102
int P_currTIME
Definition: ECLabDriver.h:51
static const iocshArg initArg0
A name for the asyn driver instance we will create - used to refer to it from EPICS DB files...
static const iocshArg initArg1
IP address used.
virtual asynStatus writeOctet(asynUser *pasynUser, const char *value, size_t maxChars, size_t *nActual)
Definition: ECLabDriver.cpp:87
static const iocshArg *const initArgs[]
Copyright © 2013 Science and Technology Facilities Council | Generated by   doxygen 1.8.5