TOBI SignalServer  0.1
/home/breidi/Dropbox/signalserver/src/hardware/brainampseries.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 <boost/numeric/conversion/cast.hpp>
00040 #include <boost/lexical_cast.hpp>
00041 #include <boost/algorithm/string.hpp>
00042 #include <math.h>
00043 
00044 #include "tia/constants.h"
00045 #include "hardware/brainampseries.h"
00046 
00047 namespace tobiss
00048 {
00049 
00050 using std::string;
00051 using std::vector;
00052 using std::map;
00053 using std::pair;
00054 using std::make_pair;
00055 
00056 using std::cout;
00057 using std::cerr;
00058 using std::endl;
00059 
00060 using boost::lexical_cast;
00061 using boost::bad_lexical_cast;
00062 using boost::algorithm::to_lower_copy;
00063 
00064 const HWThreadBuilderTemplateRegistratorWithoutIOService<BrainAmpSeries> BrainAmpSeries::factory_registrator_ ("brainamp");
00065 
00066 const float BrainAmpSeries::scaling_values_[4] = {.1f, .5f, 10.f, 152.6f };
00067 const double BRAINAMP_SAMPLING_RATE = 5000;
00068 const unsigned int MAX_NR_OF_AMPS = 4;
00069 //const unsigned int CHANNELS_PER_AMP = 32;
00070 
00071 #define DEVICE_USB    "\\\\.\\BrainAmpUSB1"   // USB device
00072 
00073 
00074 const string BrainAmpSeries::hw_low_imp_("use_low_impedance");
00075 const string BrainAmpSeries::hw_trigger_value_("trigger_hold_value");
00076 const string BrainAmpSeries::hw_trigger_line_("trigger_line");
00077 const string BrainAmpSeries::hw_250lp_("lowpass_250Hz");
00078 const string BrainAmpSeries::hw_dc_coupl_("dc_coupling");
00079 const string BrainAmpSeries::hw_resolution_("resolution");
00080 const string BrainAmpSeries::hw_calibration_("calibration_mode");
00081 const string BrainAmpSeries::hw_calib_on_("on");
00082 const string BrainAmpSeries::hw_calib_sig_("signal");
00083 const string BrainAmpSeries::hw_calib_freq_("freq");
00084 const string BrainAmpSeries::hw_value_("value");
00085 
00086 //-----------------------------------------------------------------------------
00087 
00088 BrainAmpSeries::BrainAmpSeries(ticpp::Iterator<ticpp::Element> hw)
00089   : acqu_type_(DataAcqu), dev_handle_(INVALID_HANDLE_VALUE), driver_version_(0),
00090     ds_factor_(0), trigger_line_enabled_(0), trigger_line_sig_type_(SIG_UNDEFINED)
00091 {
00092   setType("Brainamp Series");
00093 
00094   resolution_names_.insert(make_pair("100nv",  0)); // nV is in lower case because of to_lower_copy
00095   resolution_names_.insert(make_pair("500nv",  1));
00096   resolution_names_.insert(make_pair("10muv",  2));
00097   resolution_names_.insert(make_pair("152muv", 3));
00098 
00099   calibration_signals_.insert(make_pair("ramp",     0));
00100   calibration_signals_.insert(make_pair("triangle", 1));
00101   calibration_signals_.insert(make_pair("square",   2));
00102   calibration_signals_.insert(make_pair("sine",     3));
00103 
00104   channels_per_amp_.insert(make_pair(None,      make_pair("None", 0) ));
00105   channels_per_amp_.insert(make_pair(Standard,  make_pair("Standard", 32) ));
00106   channels_per_amp_.insert(make_pair(MR,        make_pair("MR", 32) ));
00107   channels_per_amp_.insert(make_pair(DCMRplus,  make_pair("DCMRplus", 32) ));
00108   channels_per_amp_.insert(make_pair(ExGMR,     make_pair("ExGMR_8", 8) ));
00109 
00110 
00111   ZeroMemory(&brainamp_settings_, sizeof(brainamp_settings_));
00112 
00113   brainamp_settings_.nChannels = 0;
00114   brainamp_settings_.nPoints = 0;
00115   brainamp_settings_.nLowImpedance = 0;
00116   brainamp_settings_.nHoldValue = 0x0;
00117 
00118   for (unsigned int n = 0; n < 256; n++)
00119   {
00120     brainamp_settings_.nChannelList[n] = 0;
00121     brainamp_settings_.n250Hertz[n] = 0;
00122     brainamp_settings_.nResolution[n] = 0;
00123     brainamp_settings_.nDCCoupling[n] = 0;
00124   }
00125 
00126 
00127   brainamp_calibration_settings_.nWaveForm  = 3;         // sine wave
00128   brainamp_calibration_settings_.nFrequency = 10000;     // 10 Hz
00129 
00130   setHardware(hw);
00131 
00132   if(!OpenUSBDevice())
00133     throw(std::runtime_error("Error opening USB device (check if a 2nd signal server is running)!") );
00134 
00135   std::vector<AmpType> amps = GetConnectedAmps();
00136   printConnectedAmplifiers(amps);
00137   checkHighestChannelNr( amps );
00138 
00139   if(ds_factor_)
00140   {
00141     initDownsamplingFilters();
00142     brainamp_settings_.nPoints = ds_factor_ * blocks_;
00143 
00144     raw_buffer_.resize( (nr_ch_ + !trigger_line_enabled_ ) * ds_factor_ * blocks_, 0);
00145     downsampling_buffer_.resize( nr_ch_ * ds_factor_ * blocks_, 0);
00146   }
00147   else
00148   {
00149     brainamp_settings_.nPoints = blocks_;
00150     raw_buffer_.resize((nr_ch_ + !trigger_line_enabled_ ) * blocks_, 0);
00151     downsampling_buffer_.resize((nr_ch_) * blocks_, 0);
00152   }
00153 
00154   //cout << "Nr ch: " << nr_ch_ << endl;
00155 
00156   //for(map<uint16_t, pair<string, uint32_t> >::iterator it = channel_info_.begin();
00157   //    it != channel_info_.end(); it++ )
00158   //    cout << "ch " << it->first << " --type: " << it->second.first << "; " << it->second.second << endl;
00159 
00160   //for(unsigned int n = 0; n < channel_types_.size(); n++)
00161   //  cout << "ch " << n << ": " << channel_types_[n] << endl;
00162   //cout << endl;
00163 
00164 
00165   samples_.resize(nr_ch_ * blocks_, 0);
00166   data_.init(blocks_, nr_ch_, channel_types_);
00167 
00168 
00169   if(acqu_type_ == DataAcqu)
00170   {
00171     DWORD bytes_returned = 0;
00172     if (!DeviceIoControl(dev_handle_, IOCTL_BA_SETUP, &brainamp_settings_, sizeof(brainamp_settings_),
00173                        NULL, 0, &bytes_returned, NULL))
00174      throw(std::runtime_error("Setup failed, error code: " +  lexical_cast<string>(GetLastError() ) ) );
00175   }
00176 
00177   unsigned int nModule = driver_version_ % 10000;
00178   unsigned int nMinor = (driver_version_ % 1000000) / 10000;
00179   unsigned int nMajor = driver_version_ / 1000000;
00180 
00181   cout << endl;
00182   cout << " --> Using Brainamp -- Mode: " << acqu_type_;
00183   cout << " -- driver version: " << nMajor << "." << nMinor << "." << nModule << endl;
00184   cout << "    fs: " << fs_ << "Hz, nr of channels: " << nr_ch_ << ", blocksize: " << blocks_ << endl;
00185   cout << endl;
00186 
00187 #ifdef DEBUG
00188   for (int n = 0; n < nr_ch_; n++)
00189   {
00190     cout << "ch: " << n << ";  nr:" <<  (int)brainamp_settings_.nChannelList[n] << ";  ";
00191     cout << "res: " <<  (int)brainamp_settings_.nResolution[ n ] << ";  ";
00192     cout << "dc: " <<  (int)brainamp_settings_.nDCCoupling[ n ] << ";  ";
00193     cout << "250Hz: " <<  (int)brainamp_settings_.n250Hertz[ n ] << endl;
00194   }
00195 #endif
00196 }
00197 
00198 //-----------------------------------------------------------------------------
00199 
00200 BrainAmpSeries::~BrainAmpSeries()
00201 {
00202   if(running_)
00203     stop();
00204 
00205   if (dev_handle_ != INVALID_HANDLE_VALUE)
00206     CloseHandle(dev_handle_);
00207 }
00208 
00209 //-----------------------------------------------------------------------------
00210 
00211 void BrainAmpSeries::run()
00212 {
00213  uint16_t pullup = 0;
00214  DWORD bytes_returned = 0;
00215  if (!DeviceIoControl(dev_handle_, IOCTL_BA_DIGITALINPUT_PULL_UP, &pullup, sizeof(pullup),
00216             NULL, 0, &bytes_returned, NULL))
00217   throw(std::runtime_error("Can't set pull up/down resistors, error code: "+  lexical_cast<string>(GetLastError() ) ) );
00218 
00219   if (!DeviceIoControl(dev_handle_, IOCTL_BA_START, &acqu_type_, sizeof(acqu_type_), NULL, 0,
00220                        &bytes_returned, NULL))
00221   {
00222     int error_code = 0;
00223     if(!DeviceIoControl(dev_handle_, IOCTL_BA_ERROR_STATE, NULL, 0, &error_code,
00224                         sizeof(error_code), &bytes_returned, NULL))
00225       throw(std::runtime_error("Run failed -- Could not retrieve error state!"  ));
00226 
00227       if(error_code != 0)
00228         throw(std::runtime_error("Run failed -- "  + getErrorMsg(error_code) ));
00229 
00230       throw(std::runtime_error("Run failed (check battery, power switch and connectors) -- Error code: "  +  lexical_cast<string>(GetLastError() ) ));
00231   }
00232   running_ = 1;
00233 }
00234 
00235 //-----------------------------------------------------------------------------
00236 
00237 void BrainAmpSeries::stop()
00238 {
00239   running_ = 0;
00240   DWORD bytes_returned = 0;
00241   if(!DeviceIoControl(dev_handle_, IOCTL_BA_STOP, NULL, 0, NULL, 0, &bytes_returned, NULL))
00242     throw(std::runtime_error("Stop failed, error code: "+  lexical_cast<string>(GetLastError() ) ) );
00243 }
00244 
00245 //-----------------------------------------------------------------------------
00246 
00247 SampleBlock<double> BrainAmpSeries::getSyncData()
00248 {
00249   if(!running_)
00250     return(data_);
00251 
00252   if(!readData())
00253   {
00254     for(uint32_t n = 0; n < samples_.size(); n++)
00255       samples_[n] = 0;
00256 
00257     data_.setSamples(samples_);
00258   }
00259   else
00260     if(ds_factor_)
00261       doDownSamplingAndFillSampleVector();
00262     else
00263       fillSampleVector();
00264 
00265   data_.setSamples(samples_);
00266   return(data_);
00267 }
00268 
00269 //-----------------------------------------------------------------------------
00270 
00271 SampleBlock<double> BrainAmpSeries::getAsyncData()
00272 {
00273   throw(std::runtime_error("BrainAmp -- Async mode not supported yet!"));
00274   return(data_);
00275 }
00276 
00277 //-----------------------------------------------------------------------------
00278 
00279 void BrainAmpSeries::setHardware(ticpp::Iterator<ticpp::Element>const &hw)
00280 {
00281   checkMandatoryHardwareTags(hw);
00282   ticpp::Iterator<ticpp::Element> ds(hw->FirstChildElement(hw_devset_, true));
00283 
00284   setDeviceSettings(ds);
00285 
00286   ticpp::Iterator<ticpp::Element> cs(hw->FirstChildElement(hw_chset_, false));
00287   if (cs != cs.end())
00288   {
00289     for(ticpp::Iterator<ticpp::Element> it(cs); ++it != it.end(); )
00290       if(it->Value() == hw_chset_)
00291       {
00292         string ex_str(type_ + " -- ");
00293         ex_str += "Multiple channel_settings found!";
00294         throw(std::invalid_argument(ex_str));
00295       }
00296       setChannelSettings(cs);
00297   }
00298 
00299   setBrainAmpChannelList();
00300   checkTriggerLineChannel();
00301 }
00302 
00303 //-----------------------------------------------------------------------------
00304 
00305 void BrainAmpSeries::setDeviceSettings(ticpp::Iterator<ticpp::Element>const &father)
00306 {
00307   //  fs_ = BRAINAMP_SAMPLING_RATE;
00308 
00309   ticpp::Iterator<ticpp::Element> elem(father->FirstChildElement(hw_fs_,true));
00310   if(elem != elem.end())
00311     setBrainAmpSamplingRate(elem);
00312 
00313   elem = father->FirstChildElement(hw_channels_,false);
00314   if(elem != elem.end())
00315     setDeviceChannels(elem);
00316 
00317   brainamp_settings_.nChannels = channel_info_.size();
00318 
00319   elem = father->FirstChildElement(hw_blocksize_,false);
00320   if(elem != elem.end())
00321     setBlocks(elem);
00322 
00323   elem = father->FirstChildElement(hw_low_imp_,false);
00324   if(elem != elem.end())
00325     setDeviceLowImp(elem);
00326 
00327   elem = father->FirstChildElement(hw_trigger_line_,false);
00328   if(elem != elem.end())
00329     setTriggerLine(elem);
00330 
00331   elem = father->FirstChildElement(hw_trigger_value_,false);
00332   if(elem != elem.end())
00333     setDeviceTriggerValue(elem);
00334 
00335   elem = father->FirstChildElement(hw_250lp_,false);
00336   if(elem != elem.end())
00337     setDeviceLowpass250(elem);
00338 
00339   elem = father->FirstChildElement(hw_dc_coupl_,false);
00340   if(elem != elem.end())
00341     setDeviceDCCoupling(elem);
00342 
00343   elem = father->FirstChildElement(hw_resolution_,false);
00344   if(elem != elem.end())
00345     setDeviceResolution(elem);
00346 
00347   elem = father->FirstChildElement(hw_calibration_,false);
00348   if(elem != elem.end())
00349     setDeviceCalibrationMode(elem);
00350 
00351 }
00352 
00353 //-----------------------------------------------------------------------------
00354 
00355 void BrainAmpSeries::setChannelSettings(ticpp::Iterator<ticpp::Element>const &father)
00356 {
00357   ticpp::Iterator<ticpp::Element> elem(father->FirstChildElement(hw_chset_sel_,false));
00358   if (elem != elem.end())
00359     setChannelSelection(elem);
00360 
00361   setBrainAmpChannelList();
00362 
00363   brainamp_settings_.nChannels = channel_info_.size();
00364 
00365   elem = father->FirstChildElement(hw_250lp_,false);
00366   if(elem != elem.end())
00367     setChannelLowpass250(elem);
00368 
00369   elem = father->FirstChildElement(hw_dc_coupl_,false);
00370   if(elem != elem.end())
00371     setChannelDCDecoupling(elem);
00372 
00373   elem = father->FirstChildElement(hw_resolution_,false);
00374   if(elem != elem.end())
00375     setChannelResolution(elem);
00376 }
00377 
00378 //-----------------------------------------------------------------------------
00379 
00380 std::string BrainAmpSeries::getErrorMsg(int error_code)
00381 {
00382  uint32_t code = error_code & 0xffff;
00383 
00384  switch (code)
00385  {
00386   case 0:
00387    break;
00388   case 1:
00389    return(string("Connection between Brainamp and USB 2 Adapter / PCI is broken.\n"
00390     "Please check connectors, switch and battery power. After the\n"
00391     "connection is established and if you wish to continue the\n"
00392     "recording, please restart the program."));
00393   case 2:
00394    return(string(
00395     "The voltage in the amplifier is too low!\n"
00396     "Check the batteries!"));
00397   case 3:
00398    return(string(
00399     "Could not establish communication with the amplifier.\n"
00400     "Check the connectors and the battery power!"));
00401   case 4:
00402    return(string("Out of synch, Barker words missing!"));
00403   case 5:
00404    return(string(
00405     "Connection between USB 2 Adapter and Computer is broken.\n"
00406     "Monitoring or recording was interrupted. Please check\n"
00407     "the USB connectors."));
00408   default:
00409    return(string("Unknown Amplifier Error\n"));
00410  }
00411  return "";
00412 }
00413 
00414 //-----------------------------------------------------------------------------
00415 
00416 bool BrainAmpSeries::OpenUSBDevice()
00417 {
00418   DWORD dwFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH;
00419 
00420   dev_handle_ = CreateFile(DEVICE_USB, GENERIC_READ | GENERIC_WRITE, 0, NULL,
00421                            OPEN_EXISTING, dwFlags, NULL);
00422 
00423   if (dev_handle_ == INVALID_HANDLE_VALUE)
00424     return(false);
00425 
00426   DWORD dwBytesReturned;
00427   DeviceIoControl(dev_handle_, IOCTL_BA_DRIVERVERSION, NULL, 0, &driver_version_, sizeof(driver_version_),
00428     &dwBytesReturned, NULL);
00429 
00430   return(true);
00431 }
00432 
00433 //-----------------------------------------------------------------------------
00434 
00435 std::vector<BrainAmpSeries::AmpType> BrainAmpSeries::GetConnectedAmps()
00436 {
00437  vector<AmpType> amplifiers(MAX_NR_OF_AMPS, None);
00438 
00439  USHORT amps[MAX_NR_OF_AMPS];
00440  DWORD dwBytesReturned;
00441 
00442  DeviceIoControl(dev_handle_, IOCTL_BA_AMPLIFIER_TYPE, NULL, 0, amps, sizeof(amps),
00443    &dwBytesReturned, NULL);
00444 
00445  for(int i = 0; i < MAX_NR_OF_AMPS; i++)
00446   amplifiers[i] = static_cast<AmpType>(amps[i]);
00447 
00448  return amplifiers;
00449 }
00450 
00451 //-----------------------------------------------------------------------------
00452 
00453 void BrainAmpSeries::checkHighestChannelNr(std::vector<AmpType> amps)
00454 {
00455  int highest_ch = 0;
00456  for(int i = 0; i < brainamp_settings_.nChannels; i++)
00457   highest_ch = max(brainamp_settings_.nChannelList[i], highest_ch);
00458 
00459  int max_nr_ch = 0;
00460  std::map<AmpType, std::pair<std::string, unsigned int> >::iterator it;
00461  for(unsigned int i = 0; i < amps.size(); i++)
00462  {
00463   it = channels_per_amp_.find(amps[i]);
00464   if( it != channels_per_amp_.end())
00465    max_nr_ch += it->second.second;
00466   else
00467    throw(std::invalid_argument(
00468      "BrainAmpSeries::checkHighestChannelNr -- Error, Amplifier type '" + boost::lexical_cast<string>(amps[i]) + "' not recognized" ));
00469  }
00470 
00471 //  unsigned int required_amps = static_cast<unsigned int>
00472 //      ( ceil( static_cast<double>( (highest_ch + 1)) / CHANNELS_PER_AMP ) );
00473 
00474  if ( (highest_ch+1) > max_nr_ch)
00475  {
00476   string ex_str("Not enough amplifiers connected !");
00477   ex_str += " -- required: ";
00478   ex_str += boost::lexical_cast<string>(highest_ch+1);
00479   ex_str += ";  available: ";
00480   ex_str += boost::lexical_cast<string>(max_nr_ch);
00481   throw(std::invalid_argument(ex_str));
00482  }
00483 }
00484 
00485 //-----------------------------------------------------------------------------
00486 
00487 void BrainAmpSeries::printConnectedAmplifiers(std::vector<AmpType> amps)
00488 {
00489  std::map<AmpType, std::pair<std::string, unsigned int> >::iterator it;
00490 
00491  cout << "    Connected BrainProducts amplifiers:" << endl;
00492  for(unsigned int i = 0; i < amps.size(); i++)
00493  {
00494   it = channels_per_amp_.find(amps[i]);
00495   if( it != channels_per_amp_.end())
00496   {
00497    cout << "     * pos: " << i << " -- " << it->second.first << " (type: ";
00498    cout << it->first << "), nr of ch: " << it->second.second << endl;
00499   }
00500   else
00501    throw(std::invalid_argument(
00502      "BrainAmpSeries::printConnectedAmplifiers -- Error, Amplifier type '" + boost::lexical_cast<string>(amps[i]) + "' not recognized" ));
00503  }
00504 }
00505 
00506 //-----------------------------------------------------------------------------
00507 
00508 void BrainAmpSeries::setBrainAmpChannelList()
00509 {
00510   #ifdef DEBUG
00511     cout << "BrainAmpSeries: setBrainAmpChannels" << endl;
00512   #endif
00513 
00514   map<uint16_t, pair<string, uint32_t> >::iterator it(channel_info_.begin());
00515   map<uint16_t, pair<string, uint32_t> >::iterator stop(channel_info_.end());
00516   unsigned int n = 0;
00517 
00518   for(  ; it != stop; it++)
00519   {
00520     brainamp_settings_.nChannelList[n] = boost::numeric_cast<CHAR>( it->first) -1;
00521     n++;
00522   }
00523 }
00524 
00525 //-----------------------------------------------------------------------------
00526 
00527 void BrainAmpSeries::setBrainAmpSamplingRate(ticpp::Iterator<ticpp::Element>const &elem)
00528 {
00529   setSamplingRate(elem);
00530 
00531   if(BRAINAMP_SAMPLING_RATE < fs_)
00532     throw(std::invalid_argument("Invalid sampling rate -- max. fs: "
00533                                 + boost::lexical_cast<string>(BRAINAMP_SAMPLING_RATE)) );
00534 
00535   if( fmod(BRAINAMP_SAMPLING_RATE, fs_) != 0.0)
00536     throw(std::invalid_argument("Invalid sampling rate -- max. fs (5kHz) must be divisible by desired fs without a rest!"));
00537 
00538   if(BRAINAMP_SAMPLING_RATE == fs_)
00539     ds_factor_ = 0;
00540   else
00541   {
00542     ds_factor_ = boost::numeric_cast<unsigned int>(BRAINAMP_SAMPLING_RATE / fs_);
00543     cout << "    Using downsampling by factor: " << ds_factor_;
00544     cout << " ( ... " << BRAINAMP_SAMPLING_RATE/ds_factor_ << " Hz sampling rate)" << endl;
00545   }
00546 }
00547 
00548 //-----------------------------------------------------------------------------
00549 
00550 void BrainAmpSeries::setDeviceLowImp(ticpp::Iterator<ticpp::Element>const &elem)
00551 {
00552   if(equalsYesOrNo(elem->GetText(true)))
00553     brainamp_settings_.nLowImpedance = 10;
00554   else
00555     brainamp_settings_.nLowImpedance = 0;
00556 }
00557 
00558 //-----------------------------------------------------------------------------
00559 
00560 void BrainAmpSeries::setDeviceTriggerValue(ticpp::Iterator<ticpp::Element>const &elem)
00561 {
00562   uint16_t value = 0;
00563   try{
00564     value = lexical_cast<uint16_t>( elem->GetText(true) );
00565   }
00566   catch(bad_lexical_cast &)
00567   {
00568     string ex_str(type_ + " -- ");
00569     ex_str += "Tag <"+ hw_trigger_value_ + "> : Value is not a unsigned short (16bit)!";
00570     throw(std::invalid_argument(ex_str));
00571   }
00572 
00573   brainamp_settings_.nHoldValue = value;
00574 }
00575 
00576 //-----------------------------------------------------------------------------
00577 
00578 void BrainAmpSeries::setDeviceLowpass250(ticpp::Iterator<ticpp::Element>const &elem)
00579 {
00580   bool lp250 = equalsOnOrOff(elem->GetText(true));
00581   for (unsigned int n = 0; n < nr_ch_; n++)
00582     brainamp_settings_.n250Hertz[n] = lp250;
00583 }
00584 
00585 //-----------------------------------------------------------------------------
00586 
00587 void BrainAmpSeries::setDeviceDCCoupling(ticpp::Iterator<ticpp::Element>const &elem)
00588 {
00589   bool dc = equalsOnOrOff(elem->GetText(true));
00590   for (unsigned int n = 0; n < nr_ch_; n++)
00591     brainamp_settings_.nDCCoupling[n] = dc;
00592 }
00593 
00594 //-----------------------------------------------------------------------------
00595 
00596 void BrainAmpSeries::setDeviceResolution(ticpp::Iterator<ticpp::Element>const &elem)
00597 {
00598   string str(elem->GetText(true));
00599   map<string, unsigned int>::iterator it;
00600   it = resolution_names_.find(to_lower_copy(str));
00601   if(it == resolution_names_.end())
00602   {
00603     cout << "  * Possible resolutions: " << endl;
00604     cout << "     ";
00605     for(it = resolution_names_.begin(); it != resolution_names_.end(); it++ )
00606       cout << it->first << ", ";
00607     cout  << endl;
00608 
00609     string e = "Resolution \"" + str + "\" not found -- please also check spelling!";
00610     throw(std::invalid_argument(e));
00611   }
00612 
00613   for (unsigned int n = 0; n < nr_ch_; n++)
00614     brainamp_settings_.nResolution[n] = resolution_names_[to_lower_copy(str)];
00615 }
00616 
00617 //-----------------------------------------------------------------------------
00618 
00619 void BrainAmpSeries::setDeviceCalibrationMode(ticpp::Iterator<ticpp::Element>const &elem)
00620 {
00621   if(!elem.Get()->HasAttribute(hw_calib_on_))
00622   {
00623     string ex_str(type_ + " -- ");
00624     ex_str += "Tag <"+hw_calibration_+"> given, "+hw_calib_on_+" attribute not given!";
00625     throw(std::invalid_argument(ex_str));
00626   }
00627   if(!elem.Get()->HasAttribute(hw_calib_sig_))
00628   {
00629     string ex_str(type_ + " -- ");
00630     ex_str += "Tag <"+hw_calibration_+"> given, "+hw_calib_sig_+" attribute not given!";
00631     throw(std::invalid_argument(ex_str));
00632   }
00633   if(!elem.Get()->HasAttribute(hw_calib_freq_))
00634   {
00635     string ex_str(type_ + " -- ");
00636     ex_str += "Tag <"+hw_calibration_+"> given, "+hw_calib_freq_+" attribute not given!";
00637     throw(std::invalid_argument(ex_str));
00638   }
00639 
00640 
00641 
00642 
00643   string str( elem.Get()->GetAttribute(hw_calib_sig_)  );
00644   map<string, unsigned int>::iterator it;
00645   it = calibration_signals_.find(to_lower_copy(str));
00646   if(it == calibration_signals_.end())
00647   {
00648     cout << "  * Possible calibration signal types: " << endl;
00649     cout << "     ";
00650     for(it = calibration_signals_.begin(); it != calibration_signals_.end(); it++ )
00651       cout << it->first << ", ";
00652     cout  << endl;
00653 
00654     string e = "Calibration signal \"" + str + "\" not found -- please also check spelling!";
00655     throw(std::invalid_argument(e));
00656   }
00657 
00658   brainamp_calibration_settings_.nWaveForm = calibration_signals_[str];
00659 
00660   double freq = 0;
00661 
00662   try{
00663     freq = lexical_cast<double>( elem.Get()->GetAttribute(hw_calib_freq_) );
00664   }
00665   catch(bad_lexical_cast &)
00666   {
00667     string ex_str(type_ + " -- ");
00668     ex_str += "Tag <"+ hw_calib_freq_ + "> : Value is not a floating point number!";
00669     throw(std::invalid_argument(ex_str));
00670   }
00671 
00672   brainamp_calibration_settings_.nFrequency =
00673       boost::numeric_cast<uint32_t>(floor(freq * 1000));  // value has to be in millihertz
00674 
00675   // TODO: implement different test signals
00676 
00677   if(equalsYesOrNo( elem.Get()->GetAttribute(hw_calib_on_) ) )
00678   {
00679     acqu_type_ = TestSignal;
00680     cout << "  -- Brainamp: Using calibration signal -- ";
00681     cout << elem.Get()->GetAttribute(hw_calib_sig_) << ";  ";
00682     cout << elem.Get()->GetAttribute(hw_calib_freq_) << " Hz" << endl;
00683 
00684     DWORD bytes_returned = 0;
00685     if (!DeviceIoControl(dev_handle_, IOCTL_BA_CALIBRATION_SETTINGS, &brainamp_calibration_settings_,
00686                          sizeof(brainamp_calibration_settings_), NULL, 0, &bytes_returned, NULL))
00687       throw(std::runtime_error("Calibration failed, error code: "+  lexical_cast<string>(GetLastError() ) ) );
00688   }
00689 
00690 }
00691 
00692 //-----------------------------------------------------------------------------
00693 
00694 void BrainAmpSeries::setChannelLowpass250(ticpp::Iterator<ticpp::Element>const &father)
00695 {
00696   ticpp::Iterator<ticpp::Element> elem = father->FirstChildElement(hw_chset_ch_,false);
00697 
00698   cout << " * Brainamp -- 250 Hz lowpass filter activated on channels:" << endl;
00699 
00700   for(  ; elem != elem.end(); elem++)
00701     if(elem->Value() == hw_chset_ch_)
00702     {
00703       if(!elem.Get()->HasAttribute(hw_ch_nr_))
00704       {
00705         string ex_str(type_ + " -- ");
00706         ex_str += "Tag <"+hw_250lp_+"> given, but channel number ("+hw_ch_nr_+") not given!";
00707         throw(std::invalid_argument(ex_str));
00708       }
00709       if(!elem.Get()->HasAttribute(hw_value_))
00710       {
00711         string ex_str(type_ + " -- ");
00712         ex_str += "Tag <"+hw_250lp_+"> given, but attribute ("+hw_value_+") (on/off) not given!";
00713         throw(std::invalid_argument(ex_str));
00714       }
00715 
00716       uint16_t ch = 0;
00717       try{
00718         ch = lexical_cast<uint16_t>( elem.Get()->GetAttribute(hw_ch_nr_) );
00719       }
00720       catch(bad_lexical_cast &)
00721       {
00722         string ex_str(type_ + " -- ");
00723         ex_str += "Tag <"+ hw_250lp_ + "> : Channel is not a number!";
00724         throw(std::invalid_argument(ex_str));
00725       }
00726       if( channel_info_.find(ch) ==  channel_info_.end() )
00727       {
00728         string ex_str(type_ + " -- ");
00729         ex_str += "Tag <"+ hw_250lp_ + "> - Channel "+ lexical_cast<string>(ch) +" not set for recording!";
00730         throw(std::invalid_argument(ex_str));
00731       }
00732 
00733       bool value = equalsOnOrOff( elem.Get()->GetAttribute(hw_value_) );
00734 
00735 
00736       brainamp_settings_.n250Hertz[ findChannelPostionInChannelList(ch) ] = value;
00737       cout << "  ... ch " << ch << " (pos " << findChannelPostionInChannelList(ch) << "): " << value << "; ";
00738 
00739     }
00740     else
00741       throw(std::invalid_argument("BrainAmpSeries::setChannelLowpass250 -- Tag not equal to \""+hw_chset_ch_+"\"!"));
00742 }
00743 
00744 //-----------------------------------------------------------------------------
00745 
00746 void BrainAmpSeries::setChannelDCDecoupling(ticpp::Iterator<ticpp::Element>const &father)
00747 {
00748   ticpp::Iterator<ticpp::Element> elem = father->FirstChildElement(hw_chset_ch_,false);
00749 
00750   cout << " * Brainamp -- DC coupling activated on channels:" << endl;
00751 
00752   for(  ; elem != elem.end(); elem++)
00753     if(elem->Value() == hw_chset_ch_)
00754     {
00755       if(!elem.Get()->HasAttribute(hw_ch_nr_))
00756       {
00757         string ex_str(type_ + " -- ");
00758         ex_str += "Tag <"+hw_dc_coupl_+"> given, but channel number ("+hw_ch_nr_+") not given!";
00759         throw(std::invalid_argument(ex_str));
00760       }
00761       if(!elem.Get()->HasAttribute(hw_value_))
00762       {
00763         string ex_str(type_ + " -- ");
00764         ex_str += "Tag <"+hw_dc_coupl_+"> given, but attribute ("+hw_value_+") (on/off) not given!";
00765         throw(std::invalid_argument(ex_str));
00766       }
00767 
00768       uint16_t ch = 0;
00769       try{
00770         ch = lexical_cast<uint16_t>( elem.Get()->GetAttribute(hw_ch_nr_) );
00771       }
00772       catch(bad_lexical_cast &)
00773       {
00774         string ex_str(type_ + " -- ");
00775         ex_str += "Tag <"+ hw_dc_coupl_ + "> : Channel is not a number!";
00776         throw(std::invalid_argument(ex_str));
00777       }
00778       if( channel_info_.find(ch) ==  channel_info_.end() )
00779       {
00780         string ex_str(type_ + " -- ");
00781         ex_str += "Tag <"+ hw_dc_coupl_ + "> - Channel "+ lexical_cast<string>(ch) +" not set for recording!";
00782         throw(std::invalid_argument(ex_str));
00783       }
00784 
00785       bool value = equalsOnOrOff( elem.Get()->GetAttribute(hw_value_) );
00786 
00787       brainamp_settings_.nDCCoupling[findChannelPostionInChannelList(ch)] = value;
00788       cout << "  ... ch " << ch << " (pos " << findChannelPostionInChannelList(ch) << "): " << value << "; ";
00789     }
00790     else
00791       throw(std::invalid_argument("BrainAmpSeries::setChannelDCDecoupling -- Tag not equal to \""+hw_chset_ch_+"\"!"));
00792 }
00793 
00794 //-----------------------------------------------------------------------------
00795 
00796 void BrainAmpSeries::setChannelResolution(ticpp::Iterator<ticpp::Element>const &father)
00797 {
00798   ticpp::Iterator<ticpp::Element> elem = father->FirstChildElement(hw_chset_ch_,false);
00799 
00800   cout << " * Brainamp -- Individual resolution set on channels:" << endl;
00801 
00802   for(  ; elem != elem.end(); elem++)
00803     if(elem->Value() == hw_chset_ch_)
00804     {
00805       if(!elem.Get()->HasAttribute(hw_ch_nr_))
00806       {
00807         string ex_str(type_ + " -- ");
00808         ex_str += "Tag <"+hw_resolution_+"> given, but channel number ("+hw_ch_nr_+") not given!";
00809         throw(std::invalid_argument(ex_str));
00810       }
00811       if(!elem.Get()->HasAttribute(hw_value_))
00812       {
00813         string ex_str(type_ + " -- ");
00814         ex_str += "Tag <"+hw_resolution_+"> given, but attribute ("+hw_value_+") not given!";
00815         throw(std::invalid_argument(ex_str));
00816       }
00817 
00818       uint16_t ch = 0;
00819       try{
00820         ch = lexical_cast<uint16_t>( elem.Get()->GetAttribute(hw_ch_nr_) );
00821       }
00822       catch(bad_lexical_cast &)
00823       {
00824         string ex_str(type_ + " -- ");
00825         ex_str += "Tag <"+ hw_resolution_ + "> : Channel is not a number!";
00826         throw(std::invalid_argument(ex_str));
00827       }
00828       if( channel_info_.find(ch) ==  channel_info_.end() )
00829       {
00830         string ex_str(type_ + " -- ");
00831         ex_str += "Tag <"+ hw_resolution_ + "> - Channel "+ lexical_cast<string>(ch) +" not set for recording!";
00832         throw(std::invalid_argument(ex_str));
00833       }
00834 
00835       string str( elem.Get()->GetAttribute(hw_value_) );
00836       map<string, unsigned int>::iterator it;
00837       it = resolution_names_.find(to_lower_copy(str));
00838       if(it == resolution_names_.end())
00839       {
00840         cout << "  * Possible resolutions: " << endl;
00841         cout << "     ";
00842         for(it = resolution_names_.begin(); it != resolution_names_.end(); it++ )
00843           cout << it->first << ", ";
00844         cout  << endl;
00845 
00846         string e = "Resolution \"" + str + "\" not found -- please also check spelling!";
00847         throw(std::invalid_argument(e));
00848       }
00849 
00850       brainamp_settings_.nResolution[findChannelPostionInChannelList(ch)] = resolution_names_[to_lower_copy(str)];
00851       cout << "  ... ch " << ch << " (pos " << findChannelPostionInChannelList(ch) << "): " << str << "; ";
00852     }
00853     else
00854       throw(std::invalid_argument("BrainAmpSeries::setChannelResolution -- Tag not equal to \""+hw_chset_ch_+"\"!"));
00855 }
00856 
00857 //-----------------------------------------------------------------------------
00858 
00859 void BrainAmpSeries::initDownsamplingFilters()
00860 {
00861   for (unsigned int n = 0; n < nr_ch_; n++)
00862     lp_filters_.push_back( IIRButterLpf<double>( BRAINAMP_SAMPLING_RATE, fs_/2.0, 5, 4, 0) );
00863 }
00864 
00865 //-----------------------------------------------------------------------------
00866 
00867 bool BrainAmpSeries::readData()
00868 {
00869   //#ifdef DEBUG
00870   //  cout << "BrainAmpSeries::readData()" << endl;
00871   //#endif
00872 
00873   int error_code = 0;
00874   DWORD bytes_returned = 0;
00875   int bytes_to_receive = raw_buffer_.size() * sizeof(short);
00876 
00877   do
00878   {
00879     if(!DeviceIoControl(dev_handle_, IOCTL_BA_ERROR_STATE, NULL, 0, &error_code,
00880                         sizeof(error_code), &bytes_returned, NULL))
00881       throw(std::runtime_error("Acquisition Error -- Could not retrieve error state!"  ));
00882 
00883     if(error_code != 0)
00884       throw(std::runtime_error("Acquisition Error -- "  + getErrorMsg(error_code) ));
00885 
00886     if(!ReadFile(dev_handle_, &raw_buffer_[0], bytes_to_receive, &bytes_returned, NULL))
00887     {
00888       cerr << "Acquisition Error (filling samples with '0'): " <<  GetLastError() << endl;
00889       cerr << " -- expected " << bytes_to_receive << " bytes, got: " << bytes_returned;
00890       cerr << " (raw buffer size/nr ch.: " << raw_buffer_.size() << "/" << nr_ch_ << ")" << endl;
00891       return(false);
00892     }
00893 
00894     if(!bytes_returned)
00895       Sleep(1);
00896   }
00897   while(!bytes_returned && running_);
00898 
00899   return(true);
00900 }
00901 
00902 //-----------------------------------------------------------------------------
00903 
00904 void BrainAmpSeries::fillSampleVector()
00905 {
00906   unsigned int nr_markers = 0;
00907 
00908   unsigned int nr_data_ch = nr_ch_;
00909   if(trigger_line_enabled_)
00910     nr_data_ch = nr_ch_ -1;
00911 
00912   //cout << "raw buffer size: " << raw_buffer_.size() << endl;
00913 
00914   for(unsigned int i = 0; i < blocks_; i++)
00915   {
00916 
00917     for(unsigned int j = 0; j < nr_data_ch; j++)
00918     {
00919       samples_[i + j*blocks_] =
00920           scaling_values_[ brainamp_settings_.nResolution[j] ] *  raw_buffer_[ i*nr_data_ch + j +nr_markers ];
00921 
00922       //cout << "data: " <<  i*nr_data_ch + j +nr_markers << "-->" << i + j*blocks_ <<  endl;
00923     }
00924 
00925     if(trigger_line_enabled_)
00926     {
00927       samples_[i + nr_data_ch*blocks_] = raw_buffer_[ i*(nr_data_ch + 1) + nr_data_ch]^ brainamp_settings_.nHoldValue;
00928       //cout << "trigger: " << i*(nr_data_ch+1) + nr_data_ch << "-->" << i + nr_data_ch*blocks_ <<  endl;
00929     }
00930 
00931     //if(trigger_line_enabled_)
00932     //  samples_[i + nr_data_ch*blocks_] = raw_buffer_[ i*nr_data_ch + nr_data_ch] ^ brainamp_settings_.nHoldValue;
00933 
00934     nr_markers++;
00935   }
00936 }
00937 //                 0123       0123
00938 //data: 0-->0     [dtdt] --> [ddtt]
00939 //data: 2-->1
00940 //trigger: 1-->2
00941 //trigger: 2-->3
00942 //
00943 //data: 0-->0
00944 //trigger: 1-->2
00945 //data: 2-->1
00946 //trigger: 2-->3
00947 
00948 
00949 //-----------------------------------------------------------------------------
00950 
00951 void BrainAmpSeries::doDownSamplingAndFillSampleVector()
00952 {
00953   #ifdef DEBUG
00954     cout << "BrainAmpSeries::doDownSamplingAndFillSampleVector()" << endl;
00955   #endif
00956 
00957   unsigned int nr_markers = 0;
00958 
00959   unsigned int nr_data_ch = nr_ch_;
00960   if(trigger_line_enabled_)
00961   {
00962     nr_data_ch = nr_ch_ -1;
00963     trigger_buffer_.clear();
00964   }
00965 
00966   for(unsigned int i = 0; i < blocks_*ds_factor_; i++)
00967   {
00968     for(unsigned int j = 0; j < nr_data_ch; j++)
00969       downsampling_buffer_[i + j*blocks_*ds_factor_] =
00970          lp_filters_[j].clock( scaling_values_[ brainamp_settings_.nResolution[j] ]
00971                                *  raw_buffer_[ i*nr_data_ch + j +nr_markers ] );
00972 
00973     if(trigger_line_enabled_)
00974       trigger_buffer_.push_back(raw_buffer_[ i*(nr_data_ch+1) + nr_data_ch]
00975                                 ^ brainamp_settings_.nHoldValue);
00976 
00977     nr_markers++;
00978   }
00979 
00980   for(unsigned int n = ds_factor_, sample = 0;
00981       n <= downsampling_buffer_.size();
00982       n+=ds_factor_, sample++ )
00983   {
00984     samples_[sample] = downsampling_buffer_[n-1];
00985   }
00986 
00987   if(trigger_line_enabled_)
00988   {
00989     for(unsigned int n = ds_factor_, sample = 0;
00990       n <= trigger_buffer_.size();
00991       n+=ds_factor_, sample++ )
00992     {
00993       samples_[nr_data_ch*blocks_ + sample] = trigger_buffer_[n-1];
00994     }
00995   }
00996 
00997 }
00998 
00999 //-----------------------------------------------------------------------------
01000 
01001 void BrainAmpSeries::setTriggerLine(ticpp::Iterator<ticpp::Element>const &elem)
01002 {
01003   #ifdef DEBUG
01004     cout << "BrainAmpSeries: setTriggerLine" << endl;
01005   #endif
01006 
01007   trigger_line_enabled_ = equalsOnOrOff(elem->GetText(true));
01008 
01009   tia::Constants cst;
01010   if(elem->HasAttribute(hw_ch_type_))
01011     trigger_line_sig_type_ = cst.getSignalFlag( elem->GetAttribute(hw_ch_type_) );
01012 }
01013 
01014 //-----------------------------------------------------------------------------
01015 
01016 void BrainAmpSeries::checkTriggerLineChannel()
01017 {
01018   #ifdef DEBUG
01019     cout << "BrainAmpSeries: checkTriggerLineChannel" << endl;
01020   #endif
01021 
01022   if(trigger_line_enabled_)
01023   {
01024     boost::uint32_t last_ch = (--channel_info_.end())->first;
01025 
01026     channel_info_[last_ch + 1] = make_pair(hw_trigger_line_, trigger_line_sig_type_);
01027     nr_ch_ += 1;
01028     homogenous_signal_type_ = 0;
01029     setChannelTypes();
01030   }
01031 }
01032 
01033 //-----------------------------------------------------------------------------
01034 
01035 unsigned int BrainAmpSeries::findChannelPostionInChannelList(boost::uint32_t ch)
01036 {
01037   for(int n = 0; n < brainamp_settings_.nChannels; n++)
01038     if(brainamp_settings_.nChannelList[n] == ch-1)
01039       return(n);
01040 
01041   throw(std::invalid_argument("BrainAmpSeries::findChannelPostionInChannelList -- \
01042                               Error: Channel not found in channel list!"));
01043 }
01044 
01045 //-----------------------------------------------------------------------------
01046 
01047 }
 All Data Structures Files Functions Variables