TOBI SignalServer  0.1
/home/breidi/Dropbox/signalserver/src/hardware/hw_access.cpp
Go to the documentation of this file.
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
 All Data Structures Files Functions Variables