TOBI SignalServer
0.1
|
00001 /* 00002 This file is part of the TOBI SignalServer. 00003 00004 Commercial Usage 00005 Licensees holding valid Graz University of Technology Commercial 00006 licenses may use this file in accordance with the Graz University 00007 of Technology Commercial License Agreement provided with the 00008 Software or, alternatively, in accordance with the terms contained in 00009 a written agreement between you and Graz University of Technology. 00010 00011 -------------------------------------------------- 00012 00013 GNU General Public License Usage 00014 Alternatively, this file may be used under the terms of the GNU 00015 General Public License version 3.0 as published by the Free Software 00016 Foundation and appearing in the file gpl.txt included in the 00017 packaging of this file. Please review the following information to 00018 ensure the GNU General Public License version 3.0 requirements will be 00019 met: http://www.gnu.org/copyleft/gpl.html. 00020 00021 In case of GNU General Public License Usage ,the TOBI SignalServer 00022 is distributed in the hope that it will be useful, 00023 but WITHOUT ANY WARRANTY; without even the implied warranty of 00024 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00025 GNU General Public License for more details. 00026 00027 You should have received a copy of the GNU General Public License 00028 along with the TOBI SignalServer. If not, see <http://www.gnu.org/licenses/>. 00029 00030 Copyright 2010 Graz University of Technology 00031 Contact: SignalServer@tobi-project.org 00032 */ 00033 00034 #include <Windows.h> 00035 00036 #include "hardware/gBSamp_win.h" 00037 #include "hardware/nidaqmx_wrapper.h" 00038 00039 namespace tobiss 00040 { 00041 00042 using namespace nidaqmx; 00043 00044 using boost::uint8_t; 00045 using boost::uint16_t; 00046 using boost::uint32_t; 00047 00048 00049 using std::map; 00050 using std::vector; 00051 using std::string; 00052 using std::cout; 00053 using std::endl; 00054 00055 static const double MAX_DAQ_RANGE_VOLTS = 10.0; 00056 static const double MIN_DAQ_RANGE_VOLTS = -10.0; 00057 00058 //----------------------------------------------------------------------------- 00059 00060 const HWThreadBuilderTemplateRegistratorWithoutIOService<gBSamp> gBSamp::factory_registrator_ ("gbsamp", "g.bsamp"); 00061 00062 //----------------------------------------------------------------------------- 00063 00064 gBSamp::gBSamp(ticpp::Iterator<ticpp::Element> hw) 00065 : current_block_(0), expected_values_(0), 00066 task_handle_(0), read_samples_(0), received_samples_(0), max_timeout_(0) 00067 { 00068 #ifdef DEBUG 00069 cout << "gBSamp: Constructor" << endl; 00070 #endif 00071 00072 nidaqmx_modes_map_.insert(std::make_pair(RSE, DAQmx_Val_RSE) ); 00073 nidaqmx_modes_map_.insert(std::make_pair(NRSE, DAQmx_Val_NRSE) ); 00074 nidaqmx_modes_map_.insert(std::make_pair(diff, DAQmx_Val_Diff) ); 00075 00076 setHardware(hw); 00077 00078 expected_values_ = nr_ch_ * blocks_; 00079 00080 data_.init(blocks_, nr_ch_, channel_types_); 00081 samples_.resize(expected_values_, 0); 00082 initCard(); 00083 00084 max_timeout_ = 4*blocks_/fs_; 00085 } 00086 00087 //----------------------------------------------------------------------------- 00088 00089 gBSamp::~gBSamp() 00090 { 00091 #ifdef DEBUG 00092 cout << "gBSamp: Destructor" << endl; 00093 #endif 00094 00095 stop(); 00096 00097 } 00098 00099 //----------------------------------------------------------------------------- 00100 00101 void gBSamp::run() 00102 { 00103 #ifdef DEBUG 00104 cout << "gBSamp: run" << endl; 00105 #endif 00106 00107 running_ = 1; 00108 00109 readFromDAQCard(); 00110 } 00111 00112 //----------------------------------------------------------------------------- 00113 00114 void gBSamp::stop() 00115 { 00116 #ifdef DEBUG 00117 cout << "gBSamp: stop" << endl; 00118 #endif 00119 00120 if(!running_) 00121 return; 00122 00123 running_ = 0; 00124 00125 if( task_handle_!=0 ) 00126 { 00127 checkNIDAQmxError( nidaqmx_.stopTask(task_handle_), false); 00128 checkNIDAQmxError( nidaqmx_.clearTask(task_handle_), false); 00129 } 00130 task_handle_ = 0; 00131 } 00132 00133 //----------------------------------------------------------------------------- 00134 00135 void gBSamp::readFromDAQCard() 00136 { 00137 checkNIDAQmxError( nidaqmx_.startTask(task_handle_) ); 00138 } 00139 00140 //----------------------------------------------------------------------------- 00141 00142 SampleBlock<double> gBSamp::getSyncData() 00143 { 00144 #ifdef DEBUG 00145 cout << "gBSamp: getSyncData" << endl; 00146 #endif 00147 00148 if(!running_) 00149 { 00150 std::cerr << "gBSamp: getSyncData -- Not running!" << endl; 00151 return(data_); 00152 } 00153 00154 boost::shared_lock<boost::shared_mutex> lock(rw_); 00155 received_samples_ = 0; 00156 while(received_samples_ < blocks_) 00157 { 00158 checkNIDAQmxError( nidaqmx_.readAnalogF64(task_handle_, blocks_ , max_timeout_, 00159 DAQmx_Val_GroupByChannel, &samples_[received_samples_], 00160 samples_.size()-received_samples_, &read_samples_, 0) ); 00161 received_samples_ += read_samples_; 00162 } 00163 00164 for(unsigned int m = 0; m < channel_info_.size() ; m++) 00165 for(unsigned int n = 0; n < blocks_; n++) 00166 { 00167 samples_[ (blocks_*m) +n] *= scaling_factors_[m]; 00168 } 00169 00170 data_.setSamples(samples_); 00171 lock.unlock(); 00172 00173 return(data_); 00174 } 00175 00176 //----------------------------------------------------------------------------- 00177 00178 SampleBlock<double> gBSamp::getAsyncData() 00179 { 00180 #ifdef DEBUG 00181 cout << "gBSamp: getAsyncData" << endl; 00182 #endif 00183 00184 throw(std::runtime_error("gBSamp::getAsyncData -- Async data acquisition not available for g.BSamp yet!")); 00185 } 00186 00187 //----------------------------------------------------------------------------- 00188 00189 void gBSamp::initCard() 00190 { 00191 std::string channel_list; 00192 00193 for(map<uint16_t, std::pair<string, uint32_t> >::iterator it = channel_info_.begin(); 00194 it != channel_info_.end(); it++) 00195 { 00196 channel_list += device_id_ + "/ai"; 00197 channel_list += boost::lexical_cast<std::string>( it->first - 1 ); 00198 channel_list += ","; 00199 } 00200 channel_list.erase(channel_list.size()-1); 00201 00202 checkNIDAQmxError( nidaqmx_.createTask("",&task_handle_) ); 00203 00204 nidaqmx::int32 mode_id = getDAQmxModeID(daq_mode_); 00205 00206 checkNIDAQmxError( nidaqmx_.createAIVoltageChan(task_handle_, channel_list.c_str(), "", 00207 mode_id, MIN_DAQ_RANGE_VOLTS, MAX_DAQ_RANGE_VOLTS, 00208 DAQmx_Val_Volts, 0)); 00209 00210 00211 checkNIDAQmxError( nidaqmx_.cfgSampClkTiming(task_handle_, 0, fs_, DAQmx_Val_Rising, 00212 DAQmx_Val_HWTimedSinglePoint, blocks_)); 00213 00214 checkNIDAQmxError( nidaqmx_.cfgInputBuffer(task_handle_, 0) ); 00215 } 00216 00217 //----------------------------------------------------------------------------- 00218 00219 00220 void gBSamp::checkNIDAQmxError(nidaqmx::int32 error_code, bool throw_on_failure) 00221 { 00222 if(error_code) 00223 { 00224 char error_string[1024]; 00225 nidaqmx_.getErrorString(error_code, error_string, 1024); 00226 std::string error_msg (" -- An error occured during NIDAQmx operations -- Code: "); 00227 error_msg += boost::lexical_cast<std::string>(error_code); 00228 error_msg += " ... "; 00229 error_msg += error_string; 00230 std::cerr << error_msg << std::endl; 00231 if(throw_on_failure) 00232 throw std::runtime_error(error_msg); 00233 } 00234 } 00235 00236 //----------------------------------------------------------------------------- 00237 00238 nidaqmx::int32 gBSamp::getDAQmxModeID(daq_mode_type val) 00239 { 00240 std::map<daq_mode_type, nidaqmx::int32>::iterator it; 00241 it = nidaqmx_modes_map_.find(val); 00242 00243 if(it == nidaqmx_modes_map_.end()) 00244 { 00245 string e = "g.BSamp NIDAQmx mode \"" + boost::lexical_cast<string>(val) + "\" not found!"; 00246 throw(std::invalid_argument(e)); 00247 } 00248 00249 return(it->second); 00250 } 00251 00252 //----------------------------------------------------------------------------- 00253 00254 } // Namespace tobiss 00255