OSDN Git Service

first
[psychlops/cpp.git] / psychlops / extension / devices / psychlops_devices_nidaqmx.cpp
1 /*
2  *  psychlops_devices_nidaqmxbase.cpp
3  *  Psychlops Standard Library (Universal)
4  *
5  *  Last Modified 2009/04/14 by Kenchi HOSOKAWA
6  *  (C) 2009 Kenchi HOSOKAWA, Kazushi MARUYA, Takao SATO
7  */
8
9 #include <iostream>
10 #include <sstream>
11 #include <math.h>
12 #include "../../core/math/psychlops_m_util.h"
13 #include "psychlops_devices_nidaqmx.h"
14
15
16 #if !defined(___EXTENSIONS___)
17
18 namespace Psychlops {
19 namespace Devices {
20
21         double normalize_through_(double val) {
22                 return val;
23         }
24
25         AnalogInput_NIDAQmx::AnalogInput_NIDAQmx(const char* devname) : api(0) {}
26         AnalogInput_NIDAQmx::AnalogInput_NIDAQmx(double freq, const char* devname) : api(0) {}
27         AnalogInput_NIDAQmx::~AnalogInput_NIDAQmx() {}
28         double AnalogInput_NIDAQmx::get() { return 0; }
29         int AnalogInput_NIDAQmx::get(double* buf, int length, double timeout_second) { return 0; }
30         double AnalogInput_NIDAQmx::samplingRate() { return 0; }
31         void AnalogInput_NIDAQmx::samplingRate(double sample_per_sec) {}
32
33
34         double AnalogInput_NIDAQmx::getSamplingRate() { return 0; }
35         double AnalogInput_NIDAQmx::getLatency() { return 0; }
36         double AnalogInput_NIDAQmx::getJitterSD() { return 0; }
37         Interval AnalogInput_NIDAQmx::getRange() { Interval i; return 0<=i<=5; }
38         bool AnalogInput_NIDAQmx::isAnalog() { return true; }
39         void AnalogInput_NIDAQmx::put(double v) { ; }
40         void AnalogInput_NIDAQmx::pulse(double v) { ; }
41         void AnalogInput_NIDAQmx::keep(double v) { ; }
42
43
44         AnalogOutput_NIDAQmx::AnalogOutput_NIDAQmx(const char* devname) : api(0) {}
45         AnalogOutput_NIDAQmx::~AnalogOutput_NIDAQmx() {}
46         void AnalogOutput_NIDAQmx::put(double val) {}
47         void AnalogOutput_NIDAQmx::pulse(double val) {}
48         void AnalogOutput_NIDAQmx::keep(double val) {}
49         void AnalogOutput_NIDAQmx::setVoltage(double val, const char* devname) {}
50
51         double AnalogOutput_NIDAQmx::getLatency() { return 0; }
52         double AnalogOutput_NIDAQmx::getJitterSD() { return 0; }
53         Interval AnalogOutput_NIDAQmx::getRange() { Interval i; return 0<=i<=5; }
54         bool AnalogOutput_NIDAQmx::isAnalog() { return true; }
55         double AnalogOutput_NIDAQmx::get() { return 0; }
56
57
58         NIDAQmx::NIDAQmx()
59         {
60                 ain = 0;
61                 aout = 0;
62         }
63         NIDAQmx::~NIDAQmx() {}
64         void NIDAQmx::open(const char* devname) {}
65         void NIDAQmx::open(double freq, const char* devname) {}
66         double NIDAQmx::get() { return 0; }
67         void NIDAQmx::put(double val) {}
68         void NIDAQmx::keep(double val) {}
69         void NIDAQmx::pulse(double val) {}
70         int NIDAQmx::get(double* buf, int length, double timeout_second) { return 1; }
71         void NIDAQmx::setSamplingRate(double sample_per_sec) {}
72
73         double NIDAQmx::getSamplingRate() { return 0; }
74         double NIDAQmx::getLatency() { return 0; }
75         double NIDAQmx::getJitterSD() { return 0; }
76         Interval NIDAQmx::getRange() { Interval i; return 0<=i<=5; }
77         bool NIDAQmx::isAnalog() { return true; }
78 }
79 }       /*      <- namespace Psycholops         */
80 #else
81
82 #if defined(__APPLE__)
83 #include "/Applications/National Instruments/NI-DAQmx Base/includes/NIDAQmxBase.h"
84 #elif defined(__BORLANDC__)
85 #define WIN32
86 #include "C:\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include\NIDAQmx.h"
87 #undef WIN32
88 #else
89 #include "C:\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include\NIDAQmx.h"
90 #endif
91
92 #include "../../core/ApplicationInterfaces/psychlops_code_exception.h"
93
94
95 namespace Psychlops {
96
97 namespace Devices {
98
99 #if defined(__APPLE__)
100 #if defined(DYLIB)
101         struct NIDAQmxAPI {
102                 enum TaskType { AIVoltage, AOVoltage };
103
104         public:
105                 NIDAQmxAPI(const char* devname, TaskType dtype, double rate = 1000) { throw new Exception("NIDAQmx: Mac OS X is not supported."); }
106                 ~NIDAQmxAPI() { throw new Exception("NIDAQmx: Mac OS X is not supported."); }
107                 const double getOneShot() const { throw new Exception("NIDAQmx: Mac OS X is not supported."); return 0; }
108                 const int getSamples(float64 *f, int32 num, double timeout) const { throw new Exception("NIDAQmx: Mac OS X is not supported."); return 0; }
109                 void putOneShot(float64 f) const { throw new Exception("NIDAQmx: Mac OS X is not supported."); }
110                 void setSamplingRate(float64 f) const { throw new Exception("NIDAQmx: Mac OS X is not supported."); }
111         };
112 #else
113         int NIDAQmxAPIcount = 0;
114         struct NIDAQmxAPI {
115                 enum TaskType { AIVoltage, AOVoltage };
116                 TaskHandle taskHandle;
117                 TaskType type;
118
119         public:
120                 NIDAQmxAPI(const char* devname, TaskType dtype, double freq) {
121                         int32 err;
122                         type = dtype;
123                         std::stringstream taskname("");
124                         for(int i=0; i<64; i++) {
125                                 if(*(devname+i)==0) { break; }
126                                 taskname << (*(devname+i)!='/' ? *(devname+i) : '_');
127                         }
128                         taskname << ++NIDAQmxAPIcount;
129                         err = DAQmxBaseCreateTask(taskname.str().c_str(), &taskHandle);
130                         if(err!=0) throwError();
131                         switch(type) {
132                                 case AIVoltage:
133                                         err = DAQmxBaseCreateAIVoltageChan( taskHandle, devname, NULL, DAQmx_Val_Diff, 0, 5, DAQmx_Val_Volts, NULL);
134                                         if(err!=0) throwError();
135                                         //setSamplingRate(freq);
136                                         break;
137                                 case AOVoltage:
138                                         err = DAQmxBaseCreateAOVoltageChan( taskHandle, devname, NULL, 0, 5, DAQmx_Val_Volts, NULL);
139                                         if(err!=0) throwError();
140                                         break;
141                                 default:
142                                         throw new Exception("NIDAQmx: Illigal Task Type.");
143                         }
144                         DAQmxBaseStartTask (taskHandle);
145                         if(err!=0) throwError();
146                 }
147                 virtual ~NIDAQmxAPI() {
148                         DAQmxBaseStopTask(taskHandle);
149                         DAQmxBaseClearTask(taskHandle);
150                 }
151                 const double getOneShot() const {
152                         float64 value[16];
153                         int32 aaaa, err;
154                         err = DAQmxBaseReadAnalogF64(taskHandle, 8, 0.01, DAQmx_Val_GroupByChannel, value, 1, &aaaa, NULL);
155                         if(err!=0) throwError();
156                         return value[0];
157                 }
158                 const int getSamples(float64 *f, int32 num, uInt32 timeout) const {
159                         int32 aaaa, err;
160                         err = DAQmxBaseReadAnalogF64(taskHandle, num, timeout, DAQmx_Val_GroupByChannel, f, num, &aaaa, NULL);
161                         if(err!=0) throwError();
162                         return aaaa;
163                 }
164                 void putOneShot(float64 f) const {
165                         float64 value[8] = {f,f,f,f,f,f,f,f};
166                         if(value[0]<0 || value[0]>5) return;
167                         int32 aaaa, err;
168                         err = DAQmxBaseWriteAnalogF64(taskHandle, 1, FALSE, 0.1, DAQmx_Val_GroupByChannel, value, &aaaa, NULL);
169                         if(err!=0) throwError();
170                 }
171                 void putSamples(float64 *value, int num) const {
172                         //if(value[0]<0 || value[0]>5) return;
173                         int32 aaaa, err;
174                         err = DAQmxBaseWriteAnalogF64(taskHandle, 1, FALSE, 0.1, DAQmx_Val_GroupByChannel, value, &aaaa, NULL);
175                         if(err!=0) throwError();
176                 }
177                 void setSamplingRate(float64 freq) const {
178                         int32 err;
179                         err = DAQmxBaseCfgSampClkTiming(taskHandle, NULL, freq, DAQmx_Val_Rising, DAQmx_Val_ContSamps, (uInt32)ceil(freq));
180                         if(err!=0) throwError();
181                 }
182                 void throwError() const {
183                         char msg[256];
184                         DAQmxBaseGetExtendedErrorInfo (msg, 256);
185                         std::string s(msg);
186                         throw new Exception(s);
187                 }
188
189         };
190 #endif
191 #else
192         struct NIDAQmxAPI {
193                 enum TaskType { AIVoltage, AOVoltage };
194                 TaskHandle taskHandle;
195                 TaskType type;
196
197                 public:
198                 NIDAQmxAPI(const char* devname, TaskType dtype, double rate = 1000) {
199                         int32 err;
200                         type = dtype;
201                         char taskname[64];
202                         for(int i=0; i<64; i++) {
203                                 if(*(devname+i)==0) { taskname[i] = 0; break; }
204                                 taskname[i] = (*(devname+i)!='/' ? *(devname+i) : '_');
205                         }
206                         err = DAQmxCreateTask (taskname, &taskHandle);
207                         if(err!=0) throwError();
208                         switch(type) {
209                                 case AIVoltage:
210                                         err = DAQmxCreateAIVoltageChan( taskHandle, devname, NULL, DAQmx_Val_Diff, -5, 5, DAQmx_Val_Volts, NULL);
211                                         if(err!=0) throwError();
212                                         //setSamplingRate(rate);
213                                         break;
214                                 case AOVoltage:
215                                         err = DAQmxCreateAOVoltageChan( taskHandle, devname, NULL, 0, 5, DAQmx_Val_Volts, NULL);
216                                         if(err!=0) throwError();
217                                         break;
218                                 default:
219                                         throw new Exception("NIDAQmx: Illigal Task Type.");
220                         }
221                         err = DAQmxStartTask( taskHandle );
222                         if(err!=0) throwError();
223                 }
224                 virtual ~NIDAQmxAPI() {
225                         DAQmxStopTask(taskHandle);
226                         DAQmxClearTask(taskHandle);
227                 }
228                 const double getOneShot() const {
229                         float64 value[16];
230                         int32 aaaa, err;
231                         err = DAQmxReadAnalogF64(taskHandle, 1, 0.01, DAQmx_Val_GroupByChannel, value, 1, &aaaa, NULL);
232                         if(err!=0) throwError();
233                         return value[0];
234                 }
235                 const int getSamples(float64 *f, int32 num, uInt32 timeout) const {
236                         int32 aaaa, err;
237                         err = DAQmxReadAnalogF64(taskHandle, num, timeout, DAQmx_Val_GroupByChannel, f, num, &aaaa, NULL);
238                         if(err!=0) throwError();
239                         return aaaa;
240                 }
241                 void putOneShot(float64 f) const {
242                         float64 value[8] = {f,f,f,f,f,f,f,f};
243                         if(value[0]<0 || value[0]>5) return;
244                         int32 aaaa, err;
245                         err = DAQmxWriteAnalogF64(taskHandle, 1, FALSE, 0.01, DAQmx_Val_GroupByChannel, value, &aaaa, NULL);
246                         if(err!=0) throwError();
247                 }
248                 void setSamplingRate(float64 f) const {
249                         int32 err;
250                         err = DAQmxCfgSampClkTiming(taskHandle, NULL, f, DAQmx_Val_Rising, DAQmx_Val_ContSamps, (int)ceil(f));
251                         if(err!=0) throwError();
252                 }
253                 void throwError() const {
254                         char msg[256];
255                         DAQmxGetExtendedErrorInfo (msg, 256);
256                         std::string s(msg);
257                         throw new Exception(s);
258                 }
259         };
260 #endif
261
262 /*
263         double normalize_exponential(double val) {
264                 double sign = (val<0 ? -1 : 1);
265                 return sign * factor*pow(Math::abs(val), exponent) + intercept;
266         }
267 */
268
269
270         double normalize_through_(double val) {
271                 return val;
272         }
273
274
275
276         AnalogInput_NIDAQmx::AnalogInput_NIDAQmx(const char* devname) : api(0) {
277                 normalize = &normalize_through_;
278                 api = new NIDAQmxAPI(devname, NIDAQmxAPI::AIVoltage, 10000.0);
279         }
280         AnalogInput_NIDAQmx::AnalogInput_NIDAQmx(double freq, const char* devname) : api(0) {
281                 normalize = &normalize_through_;
282                 api = new NIDAQmxAPI(devname, NIDAQmxAPI::AIVoltage, freq);
283         }
284         AnalogInput_NIDAQmx::~AnalogInput_NIDAQmx() {
285                 if(api!=0) delete api;
286         }
287         double AnalogInput_NIDAQmx::get() {
288                 return normalize(api->getOneShot());
289         }
290         int AnalogInput_NIDAQmx::get(double* buf, int length, double timeout_second) {
291                 return api->getSamples(buf, length, timeout_second);
292         }
293         double AnalogInput_NIDAQmx::samplingRate() {
294                 return 0;
295         }
296         void AnalogInput_NIDAQmx::samplingRate(double sample_per_sec) {
297                 api->setSamplingRate(sample_per_sec);
298         }
299
300
301         double AnalogInput_NIDAQmx::getSamplingRate() { return 0; }
302         double AnalogInput_NIDAQmx::getLatency() { return 0; }
303         double AnalogInput_NIDAQmx::getJitterSD() { return 0; }
304         Interval AnalogInput_NIDAQmx::getRange() { Interval i; return 0<=i<=5; }
305         bool AnalogInput_NIDAQmx::isAnalog() { return true; }
306         void AnalogInput_NIDAQmx::put(double v) { ; }
307         void AnalogInput_NIDAQmx::pulse(double v) { ; }
308         void AnalogInput_NIDAQmx::keep(double v) { ; }
309
310
311
312
313
314
315         AnalogOutput_NIDAQmx::AnalogOutput_NIDAQmx(const char* devname) : api(0) {
316                 denormalize = &normalize_through_;
317                 api = new NIDAQmxAPI(devname, NIDAQmxAPI::AOVoltage, 10.0);
318         }
319         AnalogOutput_NIDAQmx::~AnalogOutput_NIDAQmx() {
320                 if(api!=0) delete api;
321         }
322         void AnalogOutput_NIDAQmx::put(double val) {
323                 api->putOneShot(denormalize(val));
324         }
325         void AnalogOutput_NIDAQmx::pulse(double val) {
326                 api->putOneShot(denormalize(val));
327         }
328         void AnalogOutput_NIDAQmx::keep(double val) {
329                 api->putOneShot(denormalize(val));
330         }
331         void AnalogOutput_NIDAQmx::setVoltage(double val, const char* devname) {
332                 AnalogOutput_NIDAQmx mx(devname);
333                 mx.put(val);
334         }
335
336
337
338         double AnalogOutput_NIDAQmx::getLatency() { return 0; }
339         double AnalogOutput_NIDAQmx::getJitterSD() { return 0; }
340         Interval AnalogOutput_NIDAQmx::getRange() { Interval i; return 0<=i<=5; }
341         bool AnalogOutput_NIDAQmx::isAnalog() { return true; }
342         double AnalogOutput_NIDAQmx::get() { return 0; }
343
344
345
346
347
348         NIDAQmx::NIDAQmx()
349         {
350                 ain = 0;
351                 aout = 0;
352         }
353         NIDAQmx::~NIDAQmx()
354         {
355                 if(ain!=0) delete ain;
356                 if(aout!=0) delete aout;
357         }
358         void NIDAQmx::open(const char* devname)
359         {
360                 ain = new NIDAQmxAPI(devname, NIDAQmxAPI::AIVoltage, 10000.0);;
361                 aout = new NIDAQmxAPI(devname, NIDAQmxAPI::AOVoltage, 10.0);
362         }
363         void NIDAQmx::open(double freq, const char* devname)
364         {
365                 ain = new NIDAQmxAPI(devname, NIDAQmxAPI::AIVoltage, freq);;
366                 aout = new NIDAQmxAPI(devname, NIDAQmxAPI::AOVoltage, 10.0);
367         }
368         double NIDAQmx::get()
369         {
370                 return ain!=0 ? (ain->getOneShot()) : 0;
371         }
372         void NIDAQmx::put(double val) {
373                 if(aout!=0) aout->putOneShot(val);
374         }
375         void NIDAQmx::pulse(double val) {
376                 if(aout!=0) aout->putOneShot(val);
377         }
378         void NIDAQmx::keep(double val) {
379                 if(aout!=0) aout->putOneShot(val);
380         }
381         int NIDAQmx::get(double* buf, int length, double timeout_second) {
382                 return ain!=0 ? ain->getSamples(buf, length, timeout_second) : 0;
383         }
384         void NIDAQmx::setSamplingRate(double sample_per_sec) {
385                 ain->setSamplingRate(sample_per_sec);
386         }
387
388         double NIDAQmx::getSamplingRate() { return 0; }
389         double NIDAQmx::getLatency() { return 0; }
390         double NIDAQmx::getJitterSD() { return 0; }
391         Interval NIDAQmx::getRange() { Interval i; return 0<=i<=5; }
392         bool NIDAQmx::isAnalog() { return true; }
393
394
395
396 }
397
398 }       /*      <- namespace Psycholops         */
399
400
401 #endif