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 <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 }