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 "hardware/gBSamp_unix.h" 00035 00036 #include "hardware/hw_thread_builder.h" 00037 #include "tia/constants.h" 00038 00039 #include <comedilib.h> 00040 #include <boost/cstdint.hpp> 00041 00042 // STL 00043 #include <iostream> 00044 00045 namespace tobiss 00046 { 00047 using boost::uint8_t; 00048 using boost::uint16_t; 00049 using boost::uint32_t; 00050 00051 using std::map; 00052 using std::vector; 00053 using std::string; 00054 using std::cout; 00055 using std::endl; 00056 using std::pair; 00057 using std::cerr; 00058 00059 //----------------------------------------------------------------------------- 00060 00061 const HWThreadBuilderTemplateRegistratorWithoutIOService<gBSamp> gBSamp::factory_registrator_ ("gbsamp", "g.bsamp"); 00062 00063 #define SUBDEVICE_AI 0 //subdevice for analog input 00064 #define PREF_RANGE 0 //range -10V - +10V 00065 static const int buf_size = 1000; 00066 00067 //----------------------------------------------------------------------------- 00068 00069 00070 gBSamp::gBSamp(ticpp::Iterator<ticpp::Element> hw) 00071 : first_run_(1) 00072 { 00073 #ifdef DEBUG 00074 cout << "gBSamp: Constructor" << endl; 00075 #endif 00076 00077 setHardware(hw); 00078 00079 expected_values_ = nr_ch_ * blocks_; 00080 00081 data_.init(blocks_, nr_ch_, channel_types_); 00082 samples_.resize(expected_values_, 0); 00083 00084 if( initCard() != 0) 00085 throw(std::invalid_argument("gBSamp: not initialized, please restart") ); 00086 } 00087 00088 //----------------------------------------------------------------------------- 00089 00090 gBSamp::~gBSamp() 00091 { 00092 #ifdef DEBUG 00093 cout << "gBSamp: Destructor" << endl; 00094 #endif 00095 00096 if(device_) 00097 { 00098 // comedi_cancel(device_, 0); 00099 comedi_close(device_); 00100 } 00101 00102 if( channel_list_ ) 00103 delete [] channel_list_; 00104 channel_list_ = 0; 00105 } 00106 00107 //----------------------------------------------------------------------------- 00108 00109 void gBSamp::run() 00110 { 00111 #ifdef DEBUG 00112 cout << "gBSamp: run" << endl; 00113 #endif 00114 00115 running_ = 1; 00116 00117 } 00118 00119 //----------------------------------------------------------------------------- 00120 00121 void gBSamp::stop() 00122 { 00123 #ifdef DEBUG 00124 cout << "gBSamp: stop" << endl; 00125 #endif 00126 00127 running_ = 0; 00128 00129 if(device_) 00130 { 00131 // comedi_cancel(device_, 0); 00132 comedi_close(device_); 00133 } 00134 } 00135 00136 //----------------------------------------------------------------------------- 00137 00138 SampleBlock<double> gBSamp::getSyncData() 00139 { 00140 #ifdef DEBUG 00141 cout << "gBSamp: getSyncData" << endl; 00142 #endif 00143 00144 if(!running_) 00145 { 00146 cout << "Not running!" << endl; 00147 return(data_); 00148 } 00149 00150 boost::shared_lock<boost::shared_mutex> lock(rw_); 00151 sampl_t buf[buf_size]; 00152 00153 comedi_get_buffer_contents(device_,0); 00154 int temp = expected_values_; 00155 int bytes_read = 0; 00156 int samples_read = 0; 00157 00158 00159 while(temp>0) // isn't this a little bit dangerous!? 00160 { 00161 bytes_read = read(comedi_fileno(device_), buf+samples_read, temp*sizeof(sampl_t)); 00162 temp -= bytes_read/sizeof(sampl_t); 00163 samples_read += bytes_read/sizeof(sampl_t); 00164 // if((bytes_read < 0) || (bytes_read % 2 != 0)) cout << "Error: Bytes read are " << bytes_read << endl; 00165 } 00166 00167 // what happens now, if we got more bytes than we expected? 00168 00169 map<uint16_t, pair<string, uint32_t> >::iterator it = channel_info_.begin(); 00170 int k=0; 00171 for(int i=0; i < nr_ch_; it++) 00172 { 00173 range_info_ = comedi_get_range(device_, SUBDEVICE_AI, (it->first - 1), 0); 00174 maxdata_ = comedi_get_maxdata(device_, SUBDEVICE_AI, (it->first - 1)); 00175 for(int j = 0; j < blocks_; j++) 00176 { 00177 samples_[k++] = comedi_to_phys(buf[j*nr_ch_+i], range_info_, maxdata_); 00178 } 00179 i++; 00180 } 00181 00182 for(unsigned int m = 0; m < channel_info_.size() ; m++) 00183 for(unsigned int n = 0; n < blocks_; n++) 00184 { 00185 samples_[ (blocks_*m) +n] *= scaling_factors_[m]; 00186 } 00187 00188 data_.setSamples(samples_); 00189 samples_available_ = false; 00190 lock.unlock(); 00191 00192 return(data_); 00193 } 00194 00195 //----------------------------------------------------------------------------- 00196 00197 SampleBlock<double> gBSamp::getAsyncData() 00198 { 00199 #ifdef DEBUG 00200 cout << "gBSamp: getAsyncData" << endl; 00201 #endif 00202 00203 throw(std::runtime_error("gBSamp::getAsyncData -- Async data acquisition not available for g.BSamp yet!")); 00204 00205 return(data_); 00206 } 00207 00208 //----------------------------------------------------------------------------- 00209 00210 int gBSamp::initCard() 00211 { 00212 #ifdef DEBUG 00213 cout << "gBSamp: getAsyncData" << endl; 00214 #endif 00215 00216 device_ = comedi_open(device_id_.c_str()); 00217 if(device_==0) 00218 { 00219 cerr << "Error: " << comedi_strerror( comedi_errno() ) << endl; 00220 return -1; 00221 } 00222 00223 #ifdef DEBUG 00224 cout << "gBSamp: device opened!" << endl; 00225 #endif 00226 00227 comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER); 00228 00229 map<uint16_t, pair<string, uint32_t> >::iterator it = channel_info_.begin(); 00230 channel_list_ = new unsigned int[nr_ch_]; 00231 00232 for(int i=0; i < nr_ch_; it++) 00233 { 00234 int temp_channel = (it->first - 1); 00235 channel_list_[i] = CR_PACK(temp_channel, PREF_RANGE, AREF_GROUND); 00236 i++; 00237 } 00238 00239 comedi_cmd_.subdev = 0; 00240 comedi_cmd_.flags = TRIG_ROUND_NEAREST | TRIG_WAKE_EOS; 00241 00242 comedi_cmd_.start_src = TRIG_NOW; 00243 comedi_cmd_.start_arg = 0; 00244 00245 comedi_cmd_.scan_begin_src = TRIG_TIMER; 00246 comedi_cmd_.scan_begin_arg = (1e9/fs_); 00247 00248 comedi_cmd_.convert_src = TRIG_TIMER; 00249 comedi_cmd_.convert_arg = (1e9/(fs_*nr_ch_)); 00250 00251 comedi_cmd_.scan_end_src = TRIG_COUNT; 00252 comedi_cmd_.scan_end_arg = nr_ch_; 00253 00254 comedi_cmd_.stop_src = TRIG_NONE; 00255 comedi_cmd_.stop_arg = 0; 00256 00257 comedi_cmd_.chanlist = channel_list_; 00258 comedi_cmd_.chanlist_len = nr_ch_; 00259 00260 int i=10; 00261 while(first_run_ && i>0) 00262 { 00263 error_ = comedi_command_test(device_, &comedi_cmd_); 00264 if (error_ >= 0) 00265 { 00266 cerr << "gBSamp: Error for 1st comedi_command_test: " << error_ << endl; 00267 } 00268 error_ = comedi_command_test(device_, &comedi_cmd_); 00269 if (error_ >= 0) 00270 { 00271 cerr << "gBSamp: Error for 2nd comedi_command_test: " << error_ << endl; 00272 } 00273 error_ = comedi_command_test(device_, &comedi_cmd_); 00274 if (error_ >= 0) 00275 { 00276 cerr << "gBSamp: Error for 3nd comedi_command_test: " << error_ << endl; 00277 } 00278 error_ = comedi_command(device_, &comedi_cmd_); 00279 first_run_ = 0; 00280 if (error_ < 0) 00281 { 00282 cerr << "gBSamp: Error for comedi_command: " << error_ << endl; 00283 first_run_=1; 00284 i--; 00285 } 00286 if(!first_run_) 00287 cout << "gBSamp: comedi_command successful" << endl; 00288 } 00289 00290 return error_; 00291 } 00292 00293 //----------------------------------------------------------------------------- 00294 00295 } // Namespace tobiss