2 * psychlops_devices_nidaqmxbase.cpp
3 * Psychlops Standard Library (Universal)
5 * Last Modified 2009/04/14 by Kenchi HOSOKAWA
6 * (C) 2009 Kenchi HOSOKAWA, Kazushi MARUYA, Takao SATO
12 #include "../../core/math/psychlops_m_util.h"
13 #include "psychlops_devices_nidaqmx.h"
16 #if !defined(___EXTENSIONS___)
21 double normalize_through_(double val) {
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) {}
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) { ; }
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) {}
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; }
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) {}
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; }
79 } /* <- namespace Psycholops */
82 #if defined(__APPLE__)
83 #include "/Applications/National Instruments/NI-DAQmx Base/includes/NIDAQmxBase.h"
84 #elif defined(__BORLANDC__)
86 #include "C:\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include\NIDAQmx.h"
89 #include "C:\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include\NIDAQmx.h"
92 #include "../../core/ApplicationInterfaces/psychlops_code_exception.h"
99 #if defined(__APPLE__)
102 enum TaskType { AIVoltage, AOVoltage };
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."); }
113 int NIDAQmxAPIcount = 0;
115 enum TaskType { AIVoltage, AOVoltage };
116 TaskHandle taskHandle;
120 NIDAQmxAPI(const char* devname, TaskType dtype, double freq) {
123 std::stringstream taskname("");
124 for(int i=0; i<64; i++) {
125 if(*(devname+i)==0) { break; }
126 taskname << (*(devname+i)!='/' ? *(devname+i) : '_');
128 taskname << ++NIDAQmxAPIcount;
129 err = DAQmxBaseCreateTask(taskname.str().c_str(), &taskHandle);
130 if(err!=0) throwError();
133 err = DAQmxBaseCreateAIVoltageChan( taskHandle, devname, NULL, DAQmx_Val_Diff, 0, 5, DAQmx_Val_Volts, NULL);
134 if(err!=0) throwError();
135 //setSamplingRate(freq);
138 err = DAQmxBaseCreateAOVoltageChan( taskHandle, devname, NULL, 0, 5, DAQmx_Val_Volts, NULL);
139 if(err!=0) throwError();
142 throw new Exception("NIDAQmx: Illigal Task Type.");
144 DAQmxBaseStartTask (taskHandle);
145 if(err!=0) throwError();
147 virtual ~NIDAQmxAPI() {
148 DAQmxBaseStopTask(taskHandle);
149 DAQmxBaseClearTask(taskHandle);
151 const double getOneShot() const {
154 err = DAQmxBaseReadAnalogF64(taskHandle, 8, 0.01, DAQmx_Val_GroupByChannel, value, 1, &aaaa, NULL);
155 if(err!=0) throwError();
158 const int getSamples(float64 *f, int32 num, uInt32 timeout) const {
160 err = DAQmxBaseReadAnalogF64(taskHandle, num, timeout, DAQmx_Val_GroupByChannel, f, num, &aaaa, NULL);
161 if(err!=0) throwError();
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;
168 err = DAQmxBaseWriteAnalogF64(taskHandle, 1, FALSE, 0.1, DAQmx_Val_GroupByChannel, value, &aaaa, NULL);
169 if(err!=0) throwError();
171 void putSamples(float64 *value, int num) const {
172 //if(value[0]<0 || value[0]>5) return;
174 err = DAQmxBaseWriteAnalogF64(taskHandle, 1, FALSE, 0.1, DAQmx_Val_GroupByChannel, value, &aaaa, NULL);
175 if(err!=0) throwError();
177 void setSamplingRate(float64 freq) const {
179 err = DAQmxBaseCfgSampClkTiming(taskHandle, NULL, freq, DAQmx_Val_Rising, DAQmx_Val_ContSamps, (uInt32)ceil(freq));
180 if(err!=0) throwError();
182 void throwError() const {
184 DAQmxBaseGetExtendedErrorInfo (msg, 256);
186 throw new Exception(s);
193 enum TaskType { AIVoltage, AOVoltage };
194 TaskHandle taskHandle;
198 NIDAQmxAPI(const char* devname, TaskType dtype, double rate = 1000) {
202 for(int i=0; i<64; i++) {
203 if(*(devname+i)==0) { taskname[i] = 0; break; }
204 taskname[i] = (*(devname+i)!='/' ? *(devname+i) : '_');
206 err = DAQmxCreateTask (taskname, &taskHandle);
207 if(err!=0) throwError();
210 err = DAQmxCreateAIVoltageChan( taskHandle, devname, NULL, DAQmx_Val_Diff, -5, 5, DAQmx_Val_Volts, NULL);
211 if(err!=0) throwError();
212 //setSamplingRate(rate);
215 err = DAQmxCreateAOVoltageChan( taskHandle, devname, NULL, 0, 5, DAQmx_Val_Volts, NULL);
216 if(err!=0) throwError();
219 throw new Exception("NIDAQmx: Illigal Task Type.");
221 err = DAQmxStartTask( taskHandle );
222 if(err!=0) throwError();
224 virtual ~NIDAQmxAPI() {
225 DAQmxStopTask(taskHandle);
226 DAQmxClearTask(taskHandle);
228 const double getOneShot() const {
231 err = DAQmxReadAnalogF64(taskHandle, 1, 0.01, DAQmx_Val_GroupByChannel, value, 1, &aaaa, NULL);
232 if(err!=0) throwError();
235 const int getSamples(float64 *f, int32 num, uInt32 timeout) const {
237 err = DAQmxReadAnalogF64(taskHandle, num, timeout, DAQmx_Val_GroupByChannel, f, num, &aaaa, NULL);
238 if(err!=0) throwError();
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;
245 err = DAQmxWriteAnalogF64(taskHandle, 1, FALSE, 0.01, DAQmx_Val_GroupByChannel, value, &aaaa, NULL);
246 if(err!=0) throwError();
248 void setSamplingRate(float64 f) const {
250 err = DAQmxCfgSampClkTiming(taskHandle, NULL, f, DAQmx_Val_Rising, DAQmx_Val_ContSamps, (int)ceil(f));
251 if(err!=0) throwError();
253 void throwError() const {
255 DAQmxGetExtendedErrorInfo (msg, 256);
257 throw new Exception(s);
263 double normalize_exponential(double val) {
264 double sign = (val<0 ? -1 : 1);
265 return sign * factor*pow(Math::abs(val), exponent) + intercept;
270 double normalize_through_(double val) {
276 AnalogInput_NIDAQmx::AnalogInput_NIDAQmx(const char* devname) : api(0) {
277 normalize = &normalize_through_;
278 api = new NIDAQmxAPI(devname, NIDAQmxAPI::AIVoltage, 10000.0);
280 AnalogInput_NIDAQmx::AnalogInput_NIDAQmx(double freq, const char* devname) : api(0) {
281 normalize = &normalize_through_;
282 api = new NIDAQmxAPI(devname, NIDAQmxAPI::AIVoltage, freq);
284 AnalogInput_NIDAQmx::~AnalogInput_NIDAQmx() {
285 if(api!=0) delete api;
287 double AnalogInput_NIDAQmx::get() {
288 return normalize(api->getOneShot());
290 int AnalogInput_NIDAQmx::get(double* buf, int length, double timeout_second) {
291 return api->getSamples(buf, length, timeout_second);
293 double AnalogInput_NIDAQmx::samplingRate() {
296 void AnalogInput_NIDAQmx::samplingRate(double sample_per_sec) {
297 api->setSamplingRate(sample_per_sec);
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) { ; }
315 AnalogOutput_NIDAQmx::AnalogOutput_NIDAQmx(const char* devname) : api(0) {
316 denormalize = &normalize_through_;
317 api = new NIDAQmxAPI(devname, NIDAQmxAPI::AOVoltage, 10.0);
319 AnalogOutput_NIDAQmx::~AnalogOutput_NIDAQmx() {
320 if(api!=0) delete api;
322 void AnalogOutput_NIDAQmx::put(double val) {
323 api->putOneShot(denormalize(val));
325 void AnalogOutput_NIDAQmx::pulse(double val) {
326 api->putOneShot(denormalize(val));
328 void AnalogOutput_NIDAQmx::keep(double val) {
329 api->putOneShot(denormalize(val));
331 void AnalogOutput_NIDAQmx::setVoltage(double val, const char* devname) {
332 AnalogOutput_NIDAQmx mx(devname);
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; }
355 if(ain!=0) delete ain;
356 if(aout!=0) delete aout;
358 void NIDAQmx::open(const char* devname)
360 ain = new NIDAQmxAPI(devname, NIDAQmxAPI::AIVoltage, 10000.0);;
361 aout = new NIDAQmxAPI(devname, NIDAQmxAPI::AOVoltage, 10.0);
363 void NIDAQmx::open(double freq, const char* devname)
365 ain = new NIDAQmxAPI(devname, NIDAQmxAPI::AIVoltage, freq);;
366 aout = new NIDAQmxAPI(devname, NIDAQmxAPI::AOVoltage, 10.0);
368 double NIDAQmx::get()
370 return ain!=0 ? (ain->getOneShot()) : 0;
372 void NIDAQmx::put(double val) {
373 if(aout!=0) aout->putOneShot(val);
375 void NIDAQmx::pulse(double val) {
376 if(aout!=0) aout->putOneShot(val);
378 void NIDAQmx::keep(double val) {
379 if(aout!=0) aout->putOneShot(val);
381 int NIDAQmx::get(double* buf, int length, double timeout_second) {
382 return ain!=0 ? ain->getSamples(buf, length, timeout_second) : 0;
384 void NIDAQmx::setSamplingRate(double sample_per_sec) {
385 ain->setSamplingRate(sample_per_sec);
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; }
398 } /* <- namespace Psycholops */