TOBI SignalServer  0.1
/home/breidi/Dropbox/signalserver/src/hardware/gBSamp_win.cpp
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 
 All Data Structures Files Functions Variables