OSDN Git Service

first
[psychlops/cpp.git] / psychlops / extension / devices / psychlops_devices_nidaqmxbase.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 <math.h>
11 #include <sstream>
12
13 #include "../../core/math/psychlops_m_util.h"
14 #include "psychlops_devices_nidaqmxbase.h"
15
16
17 //#define ___EXTENSIONS___
18
19 #if !defined(___EXTENSIONS___)
20
21 namespace Psychlops {
22 namespace Devices {
23
24         double normalize_through(double val) {
25                 return val;
26         }
27         /*
28          double normalize_exponential(double val) {
29                 double sign = (val<0 ? -1 : 1);
30                 return sign * factor*pow(Math::abs(val), exponent) + intercept;
31         }
32 */
33
34         AnalogInput_NIDAQmxBase::AnalogInput_NIDAQmxBase(const char* devname) : api(0) { ; }
35         AnalogInput_NIDAQmxBase::AnalogInput_NIDAQmxBase(double freq, const char* devname) : api(0) { ; }
36         AnalogInput_NIDAQmxBase::~AnalogInput_NIDAQmxBase() { ; }
37         double AnalogInput_NIDAQmxBase::get() { return 0; }
38         int AnalogInput_NIDAQmxBase::get(double* buf, int length, double timeout_second) { return 0; }
39         double AnalogInput_NIDAQmxBase::samplingRate() { return 0; }
40         void AnalogInput_NIDAQmxBase::samplingRate(double sample_per_sec) { ; }
41
42
43         double AnalogInput_NIDAQmxBase::getLatency() { return 0; }
44         double AnalogInput_NIDAQmxBase::getJitterSD() { return 0; }
45         Interval AnalogInput_NIDAQmxBase::getRange() { Interval i; return 0<=i<=5; }
46         bool AnalogInput_NIDAQmxBase::isAnalog() { return true; }
47         void AnalogInput_NIDAQmxBase::put(double v) { ; }
48         void AnalogInput_NIDAQmxBase::pulse(double v) { ; }
49         void AnalogInput_NIDAQmxBase::keep(double v) { ; }
50
51     
52         AnalogOutput_NIDAQmxBase::AnalogOutput_NIDAQmxBase(const char* devname) : api(0) { ; }
53         AnalogOutput_NIDAQmxBase::~AnalogOutput_NIDAQmxBase() { ; }
54         void AnalogOutput_NIDAQmxBase::put(double val) { ; }
55         void AnalogOutput_NIDAQmxBase::pulse(double v) { ; }
56         void AnalogOutput_NIDAQmxBase::keep(double v) { ; }
57         void AnalogOutput_NIDAQmxBase::setVoltage(double val, const char* devname) { ; }
58
59         double AnalogOutput_NIDAQmxBase::getLatency() { return 0; }
60         double AnalogOutput_NIDAQmxBase::getJitterSD() { return 0; }
61         Interval AnalogOutput_NIDAQmxBase::getRange() { Interval i; return 0<=i<=5; }
62         bool AnalogOutput_NIDAQmxBase::isAnalog() { return true; }
63         double AnalogOutput_NIDAQmxBase::get() { return 0; }
64 }
65 }       /*      <- namespace Psycholops         */
66 #else
67
68
69 #if defined(__APPLE__)
70 #include "/Applications/National Instruments/NI-DAQmx Base/includes/NIDAQmxBase.h"
71 #elif defined(__BORLANDC__)
72 #define WIN32
73 #include "C:\Program Files\National Instruments\NI-DAQmx Base\Include\NIDAQmxBase.h"
74 #undef WIN32
75 #else
76 #include "C:\Program Files\National Instruments\NI-DAQmx Base\Include\NIDAQmxBase.h"
77 #endif
78
79 #include "../../core/ApplicationInterfaces/psychlops_code_exception.h"
80
81
82 namespace Psychlops {
83
84 namespace Devices {
85
86 #if defined(DYLIB) && defined(__APPLE__)
87         struct NIDAQmxBaseAPI {
88                 enum TaskType { AIVoltage, AOVoltage };
89
90         public:
91                 NIDAQmxBaseAPI(const char* devname, TaskType dtype, double rate = 1000) { throw new Exception("NIDAQmx: Mac OS X is not supported."); }
92                 ~NIDAQmxBaseAPI() { throw new Exception("NIDAQmx: Mac OS X is not supported."); }
93                 const double getOneShot() const { throw new Exception("NIDAQmx: Mac OS X is not supported."); return 0; }
94                 const int getSamples(float64 *f, int32 num, double timeout) const { throw new Exception("NIDAQmx: Mac OS X is not supported."); return 0; }
95                 void putOneShot(float64 f) const { throw new Exception("NIDAQmx: Mac OS X is not supported."); }
96                 void setSamplingRate(float64 f) const { throw new Exception("NIDAQmx: Mac OS X is not supported."); }
97         };
98 #else
99         int NIDAQmxBaseAPIcount = 0;
100         struct NIDAQmxBaseAPI {
101                 enum TaskType { AIVoltage, AOVoltage };
102                 TaskHandle taskHandle;
103                 TaskType type;
104
105         public:
106                 NIDAQmxBaseAPI(const char* devname, TaskType dtype, double freq) {
107                         int32 err;
108                         type = dtype;
109                         std::stringstream taskname("");
110                         for(int i=0; i<64; i++) {
111                                 if(*(devname+i)==0) { break; }
112                                 taskname << (*(devname+i)!='/' ? *(devname+i) : '_');
113                         }
114                         taskname << ++NIDAQmxBaseAPIcount;
115                         err = DAQmxBaseCreateTask(taskname.str().c_str(), &taskHandle);
116                         if(err!=0) throwError();
117                         switch(type) {
118                                 case AIVoltage:
119                                         err = DAQmxBaseCreateAIVoltageChan( taskHandle, devname, NULL, DAQmx_Val_Diff, 0, 5, DAQmx_Val_Volts, NULL);
120                                         if(err!=0) throwError();
121                                         //setSamplingRate(freq);
122                                         break;
123                                 case AOVoltage:
124                                         err = DAQmxBaseCreateAOVoltageChan( taskHandle, devname, NULL, 0, 5, DAQmx_Val_Volts, NULL);
125                                         if(err!=0) throwError();
126                                         break;
127                                 default:
128                                         throw new Exception("NIDAQmx: Illigal Task Type.");
129                         }
130                         DAQmxBaseStartTask (taskHandle);
131                         if(err!=0) throwError();
132                 }
133                 virtual ~NIDAQmxBaseAPI() {
134                         DAQmxBaseStopTask(taskHandle);
135                         DAQmxBaseClearTask(taskHandle);
136                 }
137                 const double getOneShot() const {
138                         float64 value[16];
139                         int32 aaaa, err;
140                         err = DAQmxBaseReadAnalogF64(taskHandle, 8, 0.01, DAQmx_Val_GroupByChannel, value, 1, &aaaa, NULL);
141                         if(err!=0) throwError();
142                         return value[0];
143                 }
144                 const int getSamples(float64 *f, int32 num, uInt32 timeout) const {
145                         int32 aaaa, err;
146                         err = DAQmxBaseReadAnalogF64(taskHandle, num, timeout, DAQmx_Val_GroupByChannel, f, num, &aaaa, NULL);
147                         if(err!=0) throwError();
148                         return aaaa;
149                 }
150                 void putOneShot(float64 f) const {
151                         float64 value[8] = {f,f,f,f,f,f,f,f};
152                         if(value[0]<0 || value[0]>5) return;
153                         int32 aaaa, err;
154                         err = DAQmxBaseWriteAnalogF64(taskHandle, 1, FALSE, 0.1, DAQmx_Val_GroupByChannel, value, &aaaa, NULL);
155                         if(err!=0) throwError();
156                 }
157                 void putSamples(float64 *value, int num) const {
158                         //if(value[0]<0 || value[0]>5) return;
159                         int32 aaaa, err;
160                         err = DAQmxBaseWriteAnalogF64(taskHandle, 1, FALSE, 0.1, DAQmx_Val_GroupByChannel, value, &aaaa, NULL);
161                         if(err!=0) throwError();
162                 }
163                 void setSamplingRate(float64 freq) const {
164                         int32 err;
165                         err = DAQmxBaseCfgSampClkTiming(taskHandle, NULL, freq, DAQmx_Val_Rising, DAQmx_Val_ContSamps, (uInt32)ceil(freq));
166                         if(err!=0) throwError();
167                 }
168                 void throwError() const {
169                         char msg[256];
170                         DAQmxBaseGetExtendedErrorInfo (msg, 256);
171                         std::string s(msg);
172                         throw new Exception(s);
173                 }
174
175         };
176 #endif
177
178
179         double normalize_through(double val) {
180                 return val;
181         }
182         /*
183          double normalize_exponential(double val) {
184                 double sign = (val<0 ? -1 : 1);
185                 return sign * factor*pow(Math::abs(val), exponent) + intercept;
186         }
187 */
188
189         AnalogInput_NIDAQmxBase::AnalogInput_NIDAQmxBase(const char* devname) : api(0) {
190                 normalize = &normalize_through;
191                 api = new NIDAQmxBaseAPI(devname, NIDAQmxBaseAPI::AIVoltage, 10000.0);
192         }
193         AnalogInput_NIDAQmxBase::AnalogInput_NIDAQmxBase(double freq, const char* devname) : api(0) {
194                 normalize = &normalize_through;
195                 api = new NIDAQmxBaseAPI(devname, NIDAQmxBaseAPI::AIVoltage, freq);
196         }
197         AnalogInput_NIDAQmxBase::~AnalogInput_NIDAQmxBase() {
198                 if(api!=0) delete api;
199         }
200         double AnalogInput_NIDAQmxBase::get() {
201                 return normalize(api->getOneShot());
202         }
203         int AnalogInput_NIDAQmxBase::get(double* buf, int length, double timeout_second) {
204                 return api->getSamples(buf, length, timeout_second);
205         }
206         double AnalogInput_NIDAQmxBase::samplingRate() {
207                 return 0;
208         }
209         void AnalogInput_NIDAQmxBase::samplingRate(double sample_per_sec) {
210                 api->setSamplingRate(sample_per_sec);
211         }
212
213
214         double AnalogInput_NIDAQmxBase::getLatency() { return 0; }
215         double AnalogInput_NIDAQmxBase::getJitterSD() { return 0; }
216         Interval AnalogInput_NIDAQmxBase::getRange() { Interval i; return 0<=i<=5; }
217         bool AnalogInput_NIDAQmxBase::isAnalog() { return true; }
218         void AnalogInput_NIDAQmxBase::put(double v) { ; }
219         void AnalogInput_NIDAQmxBase::pulse(double v) { ; }
220         void AnalogInput_NIDAQmxBase::keep(double v) { ; }
221
222
223
224
225         AnalogOutput_NIDAQmxBase::AnalogOutput_NIDAQmxBase(const char* devname) : api(0) {
226                 denormalize = &normalize_through;
227                 api = new NIDAQmxBaseAPI(devname, NIDAQmxBaseAPI::AOVoltage, 10.0);
228         }
229         AnalogOutput_NIDAQmxBase::~AnalogOutput_NIDAQmxBase() {
230                 if(api!=0) delete api;
231         }
232         void AnalogOutput_NIDAQmxBase::put(double val) {
233                 api->putOneShot(denormalize(val));
234         }
235         void AnalogOutput_NIDAQmxBase::setVoltage(double val, const char* devname) {
236                 AnalogOutput_NIDAQmxBase mx(devname);
237                 mx.put(val);
238         }
239         void AnalogOutput_NIDAQmxBase::pulse(double val) {
240                 api->putOneShot(denormalize(val));
241         }
242         void AnalogOutput_NIDAQmxBase::keep(double val) {
243                 api->putOneShot(denormalize(val));
244         }
245         
246
247         double AnalogOutput_NIDAQmxBase::getLatency() { return 0; }
248         double AnalogOutput_NIDAQmxBase::getJitterSD() { return 0; }
249         Interval AnalogOutput_NIDAQmxBase::getRange() { Interval i; return 0<=i<=5; }
250         bool AnalogOutput_NIDAQmxBase::isAnalog() { return true; }
251         double AnalogOutput_NIDAQmxBase::get() { return 0; }
252
253 }
254
255 }       /*      <- namespace Psycholops         */
256
257 #endif
258