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