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 00038 #include <iostream> 00039 #include <fstream> 00040 00041 #include "hardware/hw_access.h" 00042 #include "hardware/hw_thread_factory.h" 00043 #include "config/xml_parser.h" 00044 00045 #include "tia/data_packet_interface.h" 00046 00047 #ifdef TIMING_TEST 00048 #include "LptTools/LptTools.h" 00049 #define LPT1 0 00050 #define LPT2 1 00051 #endif 00052 00053 00054 namespace tobiss 00055 { 00056 using boost::uint16_t; 00057 using boost::uint32_t; 00058 00059 using std::vector; 00060 using std::string; 00061 using std::map; 00062 using std::pair; 00063 using std::cout; 00064 using std::endl; 00065 using std::make_pair; 00066 using std::hex; 00067 using std::dec; 00068 00069 //----------------------------------------------------------------------------- 00070 00071 HWAccess::HWAccess(boost::asio::io_service& io, XMLParser& parser) 00072 : master_(0), acqu_running_(0) 00073 { 00074 #ifdef DEBUG 00075 cout << "HWAccess Constructor" << endl; 00076 #endif 00077 00078 try 00079 { 00080 for(unsigned int n = 0; n < parser.getNrOfHardwareElements(); n++) 00081 { 00082 HWThread* thread = HWThreadFactory::instance().createHWThread (parser.getHardwareElementName(n), io, parser.getHardwareElement(n)); 00083 if (thread) 00084 { 00085 slaves_.push_back (thread); 00086 cout << " * " << thread->getType() << " successfully initialized" << endl; 00087 cout << " fs: " << thread->getSamplingRate(); 00088 cout << "Hz, nr of channels: " << thread->getNrOfChannels(); 00089 cout << ", blocksize: " << thread->getNrOfBlocks() << endl; 00090 } 00091 } 00092 } 00093 catch(std::invalid_argument& e) 00094 { 00095 string ex_str("Error in hardware - "); 00096 ex_str += + e.what(); 00097 throw; 00098 } 00099 catch(ticpp::Exception& e) 00100 { 00101 string ex_str("Error in hardware (TICPP exception)- "); 00102 ex_str += + e.what(); 00103 throw(std::invalid_argument(ex_str)); 00104 } 00105 00106 buildDataInfoMap(); 00107 buildFsInfoMap(); 00108 doHWSetup(); 00109 00110 #ifdef TIMING_TEST 00111 lpt_flag_ = 0; 00112 #endif 00113 } 00114 00115 //----------------------------------------------------------------------------- 00116 00117 HWAccess::~HWAccess() 00118 { 00119 #ifdef DEBUG 00120 cout << "HWaccess: Destructor" << endl; 00121 #endif 00122 00123 if(acqu_running_) 00124 stopDataAcquisition(); 00125 00126 for (unsigned int n=0; n < slaves_.size(); n++) 00127 if(slaves_[n]) 00128 delete slaves_[n]; 00129 for (unsigned int n=0; n < aperiodics_.size(); n++) 00130 if(aperiodics_[n]) 00131 delete aperiodics_[n]; 00132 00133 if(master_) 00134 delete master_; 00135 } 00136 00137 //----------------------------------------------------------------------------- 00138 00139 void HWAccess::buildDataInfoMap() 00140 { 00141 #ifdef DEBUG 00142 cout << "HWAccess: buildDataInfoMap" << endl; 00143 #endif 00144 map<uint16_t, pair<string, uint32_t> > ch_info; //( ch_nr, (name, type) ) 00145 map<uint16_t, pair<string, uint32_t> >::iterator it; 00146 00147 for(unsigned int n = 0; n < slaves_.size(); n++) 00148 { 00149 ch_info = slaves_[n]->getChannelInfoMap(); 00150 it = ch_info.begin(); 00151 00152 for(unsigned int m = 0; m < ch_info.size(); m++) 00153 { 00154 uint32_t& type = it->second.second; 00155 string& name = it->second.first; 00156 if(data_info_.find( type ) == data_info_.end()) 00157 { // signal type the first time 00158 data_info_[type] = make_pair(1,slaves_[n]->getNrOfBlocks()); 00159 } 00160 else 00161 { // signal type already found 00162 data_info_[type].first += 1; 00163 } 00164 channel_naming_[type].push_back(name); 00165 00166 it++; 00167 } 00168 } 00169 00170 // cout << "Data Info Map:" << endl; 00171 // for(map<uint32_t, pair<uint16_t, uint16_t> >::iterator d_it(data_info_.begin()); 00172 // d_it != data_info_.end(); d_it++) 00173 // { 00174 // cout << "Type: " << d_it->first << "; "; 00175 // cout << "Nr. of Ch: " << d_it->second.first << "; "; 00176 // cout << "Blocksize: " << d_it->second.second << "; " << endl; 00177 // } 00178 } 00179 //----------------------------------------------------------------------------- 00180 00181 void HWAccess::doHWSetup() 00182 { 00183 #ifdef DEBUG 00184 cout << "HWAccess: checkHWSetup" << endl; 00185 #endif 00186 00187 checkIfSingleMaster(); 00188 setAperiodics(); 00189 setMasterSlaveRatio(); 00190 reportInHomogenousDevice(master_); 00191 for(unsigned int n = 0; n < slaves_.size(); n++) 00192 reportInHomogenousDevice(slaves_[n]); 00193 } 00194 00195 //----------------------------------------------------------------------------- 00196 00197 void HWAccess::checkIfSingleMaster() 00198 { 00199 #ifdef DEBUG 00200 cout << "HWAccess: checkIfSingleMaster" << endl; 00201 #endif 00202 00203 int master_count = 0; 00204 for(unsigned int n = 0; n < slaves_.size(); n++) 00205 { 00206 master_count += slaves_[n]->isMaster(); 00207 if(slaves_[n]->isMaster()) 00208 { 00209 master_ = slaves_[n]; 00210 slaves_.erase(slaves_.begin() + n); 00211 n--; 00212 } 00213 } 00214 00215 if(master_count == 0) 00216 { 00217 string ex_str; 00218 ex_str = "HWAccess::checkIfSingleMaster() -- Error: No device defined as master!"; 00219 throw(ticpp::Exception(ex_str)); 00220 } 00221 if(master_count > 1) 00222 { 00223 string ex_str; 00224 ex_str = "HWAccess::checkIfSingleMaster() -- Error: More than 1 device defined as master!"; 00225 throw(ticpp::Exception(ex_str)); 00226 } 00227 } 00228 00229 //----------------------------------------------------------------------------- 00230 00231 void HWAccess::setAperiodics() 00232 { 00233 for(unsigned int n = 0; n < slaves_.size(); n++) 00234 { 00235 if(slaves_[n]->isAperiodic()) 00236 { 00237 aperiodics_.push_back(slaves_[n]); 00238 slaves_.erase(slaves_.begin() + n); 00239 n--; 00240 } 00241 } 00242 } 00243 00244 //----------------------------------------------------------------------------- 00245 00246 void HWAccess::setMasterSlaveRatio() 00247 { 00248 #ifdef DEBUG 00249 cout << "HWAccess: setMasterSlaveRatio" << endl; 00250 #endif 00251 00252 for(unsigned int n = 0; n < slaves_.size(); n++) 00253 { 00254 uint32_t master_ratio = master_->getSamplingRate()/master_->getNrOfBlocks(); 00255 uint32_t slave_ratio = 0; 00256 uint32_t ratio = 0; 00257 if(!slaves_[n]->getSamplingRate() || !slaves_[n]->getNrOfBlocks()) 00258 ratio = 1; 00259 else 00260 { 00261 slave_ratio = slaves_[n]->getSamplingRate()/slaves_[n]->getNrOfBlocks(); 00262 ratio = master_ratio/slave_ratio; 00263 } 00264 00265 fs_ratio_.push_back(ratio); 00266 sample_it_.push_back(ratio); 00267 00268 cout << " --> Ratio between master_ and slave nr." << n+1 << ": " << fs_ratio_.back() << endl; 00269 cout << endl; 00270 } 00271 } 00272 00273 //----------------------------------------------------------------------------- 00274 00275 void HWAccess::reportInHomogenousDevice(HWThread* dev) 00276 { 00277 #ifdef DEBUG 00278 cout << "HWAccess: reportInHomogenousDevice" << endl; 00279 #endif 00280 00281 if(!dev->hasHomogenousSignalType()) 00282 { 00283 cout << " --> \"" << dev->getType() << "\" delivering different signal types!" << endl; 00284 00285 vector<uint32_t> v = dev->getChannelTypes(); 00286 00287 cout << " -- Channel Type-List: (hex) "; 00288 for(unsigned int n = 0; n < v.size(); n++) 00289 cout << hex << v[n] << ", "; 00290 cout << dec << endl; 00291 } 00292 } 00293 00294 //----------------------------------------------------------------------------- 00295 00296 void HWAccess::startDataAcquisition() 00297 { 00298 #ifdef DEBUG 00299 cout << "HWAccess: startDataAcquisition" << endl; 00300 #endif 00301 00302 cout << endl; 00303 00304 if(acqu_running_) 00305 return; 00306 00307 if(slaves_.size()) 00308 cout << endl << " Slaves:" << endl; 00309 for(unsigned int n = 0; n < slaves_.size(); n++) 00310 { 00311 slaves_[n]->run(); 00312 cout << " * " << slaves_[n]->getType() << " successfully started" << endl; 00313 } 00314 00315 if(aperiodics_.size()) 00316 cout << endl << " Aperiodic devices:" << endl; 00317 for(unsigned int n = 0; n < aperiodics_.size(); n++) 00318 { 00319 aperiodics_[n]->run(); 00320 cout << " * " << aperiodics_[n]->getType() << " successfully started" << endl; 00321 } 00322 00323 cout << endl << " Master:" << endl; 00324 master_->run(); 00325 cout << " * " << master_->getType() << " successfully started" << endl; 00326 00327 acqu_running_ = true; 00328 } 00329 00330 //----------------------------------------------------------------------------- 00331 00332 void HWAccess::stopDataAcquisition() 00333 { 00334 #ifdef DEBUG 00335 cout << "HWAccess: stopDataAcquisition" << endl; 00336 #endif 00337 00338 if(!acqu_running_) 00339 return; 00340 00341 cout << endl; 00342 master_->stop(); 00343 cout << " * " << master_->getType() << " successfully stopped" << endl; 00344 for(unsigned int n = 0; n < slaves_.size(); n++) 00345 { 00346 slaves_[n]->stop(); 00347 cout << " * " << slaves_[n]->getType() << " successfully started" << endl; 00348 } 00349 00350 acqu_running_ = false; 00351 } 00352 00353 //----------------------------------------------------------------------------- 00354 00355 void HWAccess::fillDataPacket(tia::DataPacket* packet) 00356 { 00357 //#ifdef DEBUG 00358 // cout << "HWAccess: getDataPacket" << endl; 00359 //#endif 00360 00361 packet->reset(); 00362 00363 SampleBlock<double> sb(master_->getSyncData()); 00364 packet->setTimestamp(); 00365 00366 #ifdef TIMING_TEST 00367 int port_state = LptPortIn(LPT1,0); 00368 if(!lpt_flag_) 00369 { 00370 lpt_flag_ = 1; 00371 LptPortOut(LPT1, 0, port_state | 0x01); 00372 } 00373 else 00374 { 00375 lpt_flag_ = 0; 00376 LptPortOut(LPT1, 0, port_state & ~0x01); 00377 } 00378 #endif 00379 00380 for(int n = 0; n < sb.getNrOfSignalTypes() ; n++) 00381 packet->insertDataBlock(sb.getSignalByNr(n), sb.getFlagByNr(n), sb.getNrOfBlocks()); 00382 00383 00384 for (unsigned int n=0; n < slaves_.size(); n++) 00385 { 00386 if(sample_it_[n] == fs_ratio_[n]) 00387 { 00388 sb = slaves_[n]->getAsyncData(); 00389 for(int j = 0; j < sb.getNrOfSignalTypes() ; j++) 00390 packet->insertDataBlock(sb.getSignalByNr(j), sb.getFlagByNr(j), sb.getNrOfBlocks()); 00391 sample_it_[n] = 0; 00392 } 00393 sample_it_[n]++; 00394 } 00395 00396 for (unsigned int n=0; n < aperiodics_.size(); n++) 00397 { 00398 sb = aperiodics_[n]->getAsyncData(); 00399 for(int j = 0; j < sb.getNrOfSignalTypes() ; j++) 00400 packet->insertDataBlock(sb.getSignalByNr(j), sb.getFlagByNr(j), sb.getNrOfBlocks()); 00401 } 00402 00403 packet->incPacketID(); 00404 } 00405 00406 //----------------------------------------------------------------------------- 00407 00408 vector<uint32_t> HWAccess::getAcquiredSignalTypes() 00409 { 00410 #ifdef DEBUG 00411 cout << "HWAccess: getAcquiredSignalTypes" << endl; 00412 #endif 00413 00414 vector<uint32_t> v; 00415 for(map<uint32_t, pair<uint16_t, uint16_t> >::iterator it(data_info_.begin()); 00416 it != data_info_.end(); it++) 00417 v.push_back(it->first); 00418 return(v); 00419 } 00420 00421 //----------------------------------------------------------------------------- 00422 00423 vector<uint16_t> HWAccess::getBlockSizesPerSignalType() 00424 { 00425 #ifdef DEBUG 00426 cout << "HWAccess: getBlockSizesPerSignalType" << endl; 00427 #endif 00428 00429 vector<uint16_t> v; 00430 for(map<uint32_t, pair<uint16_t, uint16_t> >::iterator it(data_info_.begin()); 00431 it != data_info_.end(); it++) 00432 v.push_back(it->second.second); 00433 return(v); 00434 } 00435 00436 //----------------------------------------------------------------------------- 00437 00438 vector<uint16_t> HWAccess::getNrOfChannelsPerSignalType() 00439 { 00440 #ifdef DEBUG 00441 cout << "HWAccess: getNrOfChannelsPerSignalType" << endl; 00442 #endif 00443 00444 vector<uint16_t> v; 00445 for(map<uint32_t, pair<uint16_t, uint16_t> >::iterator it(data_info_.begin()); 00446 it != data_info_.end(); it++) 00447 v.push_back(it->second.first); 00448 return(v); 00449 } 00450 00451 //----------------------------------------------------------------------------- 00452 00453 uint16_t HWAccess::getNrOfChannels() 00454 { 00455 #ifdef DEBUG 00456 cout << "HWAccess: getNrOfChannels" << endl; 00457 #endif 00458 00459 uint16_t nr_ch = 0; 00460 00461 for(map<uint32_t, pair<uint16_t, uint16_t> >::iterator it(data_info_.begin()); 00462 it != data_info_.end(); it++) 00463 nr_ch += it->second.first; 00464 00465 return(nr_ch); 00466 } 00467 00468 //----------------------------------------------------------------------------- 00469 00470 void HWAccess::buildFsInfoMap() 00471 { 00472 #ifdef DEBUG 00473 cout << "HWAccess::buildFsInfoMap" << endl; 00474 #endif 00475 00476 map<uint16_t, pair<string, uint32_t> > ch_info; //( ch_nr, (name, type) ) 00477 map<uint16_t, pair<string, uint32_t> >::iterator it; 00478 00479 for(unsigned int n = 0; n < slaves_.size(); n++) 00480 { 00481 ch_info = slaves_[n]->getChannelInfoMap(); 00482 it = ch_info.begin(); 00483 00484 for(unsigned int m = 0; m < ch_info.size(); m++) 00485 { 00486 uint32_t& type = it->second.second; 00487 00488 if(fs_info_.find( type ) == fs_info_.end()) 00489 { // signal type the first time 00490 fs_info_[type] = slaves_[n]->getSamplingRate(); 00491 } 00492 else 00493 { // signal type already found 00494 if(fs_info_[type] != slaves_[n]->getSamplingRate()) 00495 throw(std::runtime_error("HWAccess::buildFsInfoMap -- Sampling Rates per Signaltype differ!")); 00496 } 00497 it++; 00498 } 00499 } 00500 } 00501 00502 //----------------------------------------------------------------------------- 00503 00504 vector<boost::uint32_t> HWAccess::getSamplingRatePerSignalType() 00505 { 00506 #ifdef DEBUG 00507 cout << "HWAccess: getSamplingRatePerSignalType" << endl; 00508 #endif 00509 00510 vector<boost::uint32_t> v; 00511 for(map<uint32_t, double>::iterator it(fs_info_.begin()); 00512 it != fs_info_.end(); it++) 00513 v.push_back(it->second); 00514 return(v); 00515 } 00516 00517 std::vector<std::string> HWAccess::getPossibleHardwareNames() 00518 { 00519 return(HWThreadFactory::instance().getPossibleHardwareNames()); 00520 } 00521 00522 //----------------------------------------------------------------------------- 00523 00524 } // Namespace tobiss