TOBI SignalServer
0.1
|
00001 /* 00002 This file is part of the TOBI signal server. 00003 00004 The TOBI signal server is free software: you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation, either version 3 of the License, or 00007 (at your option) any later version. 00008 00009 The TOBI signal server is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with Foobar. If not, see <http://www.gnu.org/licenses/>. 00016 00017 Copyright 2010 Christian Breitwieser 00018 Contact: c.breitwieser@tugraz.at 00019 */ 00020 00021 #include "hardware/sine_generator.h" 00022 00023 #include <math.h> 00024 00025 #include <boost/lexical_cast.hpp> 00026 #include <boost/bind.hpp> 00027 00028 namespace tobiss 00029 { 00030 using boost::uint8_t; 00031 using boost::uint16_t; 00032 using boost::uint32_t; 00033 00034 using boost::lexical_cast; 00035 using boost::bad_lexical_cast; 00036 00037 using std::map; 00038 using std::vector; 00039 using std::string; 00040 using std::cout; 00041 using std::endl; 00042 00043 00044 const HWThreadBuilderTemplateRegistrator<SineGenerator> SineGenerator::factory_registrator_ ("sinegen", "sinegenerator"); 00045 00046 //----------------------------------------------------------------------------- 00047 00048 SineGenerator::SineGenerator(boost::asio::io_service& io, ticpp::Iterator<ticpp::Element> hw) 00049 : HWThread(), acquiring_(0), current_block_(0), td_(0) 00050 { 00051 #ifdef DEBUG 00052 cout << "SineGenerator: Constructor" << endl; 00053 #endif 00054 00055 setType("Sine Generator"); 00056 setHardware(hw); 00057 00058 step_ = 1/static_cast<float>(fs_); 00059 cycle_dur_ = 1/static_cast<float>(fs_); 00060 boost::posix_time::microseconds period(1000000/fs_); 00061 td_ += period; 00062 00063 buffer_.init(blocks_ , nr_ch_ , channel_types_); 00064 data_.init(blocks_ , nr_ch_ , channel_types_); 00065 00066 samples_.resize(nr_ch_ ,0); 00067 t_ = new boost::asio::deadline_timer(io, td_); 00068 00069 cout << " * SineGenerator sucessfully initialized" << endl; 00070 cout << " fs: " << fs_ << "Hz, nr of channels: " << nr_ch_ << ", blocksize: " << blocks_ << endl; 00071 00072 } 00073 00074 //----------------------------------------------------------------------------- 00075 00076 void SineGenerator::run() 00077 { 00078 #ifdef DEBUG 00079 cout << "SineGenerator: run" << endl; 00080 #endif 00081 00082 running_ = 1; 00083 genSine(); 00084 cout << " * SineGenerator sucessfully started" << endl; 00085 } 00086 00087 00088 //----------------------------------------------------------------------------- 00089 00090 void SineGenerator::stop() 00091 { 00092 #ifdef DEBUG 00093 cout << "SineGenerator: stop" << endl; 00094 #endif 00095 00096 running_ = 0; 00097 cond_.notify_all(); 00098 cout << " * SineGenerator sucessfully stopped" << endl; 00099 } 00100 00101 //----------------------------------------------------------------------------- 00102 00103 SampleBlock<double> SineGenerator::getSyncData() 00104 { 00105 #ifdef DEBUG 00106 cout << "SineGenerator: getSyncData" << endl; 00107 #endif 00108 00109 if(!acquiring_) 00110 acquiring_ = 1; 00111 00112 boost::unique_lock<boost::mutex> syn(sync_mut_); 00113 while(!samples_available_ && running_) 00114 cond_.wait(syn); 00115 boost::shared_lock<boost::shared_mutex> lock(rw_); 00116 samples_available_ = false; 00117 lock.unlock(); 00118 cond_.notify_all(); 00119 syn.unlock(); 00120 return(data_); 00121 } 00122 00123 //----------------------------------------------------------------------------- 00124 00125 SampleBlock<double> SineGenerator::getAsyncData() 00126 { 00127 #ifdef DEBUG 00128 cout << "SineGenerator: getAsyncData" << endl; 00129 #endif 00130 boost::shared_lock<boost::shared_mutex> lock(rw_); 00131 samples_available_ = false; 00132 lock.unlock(); 00133 return(data_); 00134 } 00135 00136 //----------------------------------------------------------------------------- 00137 00138 void SineGenerator::genSine() 00139 { 00140 #ifdef DEBUG 00141 cout << "SineGenerator: genSine" << endl; 00142 #endif 00143 00144 for(uint16_t n = 0; n < nr_ch_ ; n++) 00145 samples_[n] = sin(step_ * 2 * PI + n/4); 00146 00147 (step_ < 1-cycle_dur_ ? step_ += cycle_dur_ : step_ = 0); 00148 t_->expires_at(t_->expires_at() + td_); 00149 00150 if(blocks_ == 1) 00151 { 00152 boost::unique_lock<boost::shared_mutex> lock(rw_); 00153 boost::unique_lock<boost::mutex> syn(sync_mut_); 00154 samples_available_ = true; 00155 data_.setSamples(samples_); 00156 lock.unlock(); 00157 cond_.notify_all(); 00158 if(isMaster() && acquiring_) 00159 { 00160 cond_.wait(sync_mut_); 00161 // if( !cond_.timed_wait(sync_mut_, td_)) 00162 // cerr << "Warning: New data was not fetched fast enough!" << endl; 00163 // throw std::runtime_error("SineGenerator::genSine() -- Timeout; New data was not fetched fast enough!"); 00164 } 00165 syn.unlock(); 00166 } 00167 else 00168 { 00169 buffer_.appendBlock(samples_); 00170 current_block_++; 00171 00172 if(current_block_ == blocks_ ) 00173 { 00174 boost::unique_lock<boost::shared_mutex> lock(rw_); 00175 boost::unique_lock<boost::mutex> syn(sync_mut_); 00176 samples_available_ = true; 00177 data_ = buffer_; 00178 lock.unlock(); 00179 cond_.notify_all(); 00180 buffer_.reset(); 00181 current_block_ = 0; 00182 if(isMaster() && acquiring_) 00183 { 00184 cond_.wait(sync_mut_); 00185 // if( !cond_.timed_wait(sync_mut_, td_)) 00186 // cerr << "Warning: New data was not fetched fast enough!" << endl; 00187 // throw std::runtime_error("SineGenerator::genSine() -- Timeout; New data was not fetched fast enough!"); 00188 } 00189 syn.unlock(); 00190 } 00191 } 00192 if(running_) 00193 t_->async_wait(boost::bind(&SineGenerator::genSine, this)); 00194 } 00195 00196 //----------------------------------------------------------------------------- 00197 00198 void SineGenerator::setHardware(ticpp::Iterator<ticpp::Element>const &hw) 00199 { 00200 #ifdef DEBUG 00201 cout << "SineGenerator: setHardware" << endl; 00202 #endif 00203 00204 checkMandatoryHardwareTags(hw); 00205 ticpp::Iterator<ticpp::Element> ds(hw->FirstChildElement(hw_devset_, true)); 00206 00207 setDeviceSettings(ds); 00208 00209 ticpp::Iterator<ticpp::Element> cs(hw->FirstChildElement(hw_chset_, false)); 00210 if (cs != cs.end()) 00211 { 00212 for(ticpp::Iterator<ticpp::Element> it(cs); ++it != it.end(); ) 00213 if(it->Value() == hw_chset_) 00214 { 00215 string ex_str(type_ + " -- "); 00216 ex_str += "Multiple channel_settings found!"; 00217 throw(std::invalid_argument(ex_str)); 00218 } 00219 setChannelSettings(cs); 00220 } 00221 } 00222 00223 //----------------------------------------------------------------------------- 00224 00225 void SineGenerator::setDeviceSettings(ticpp::Iterator<ticpp::Element>const &father) 00226 { 00227 #ifdef DEBUG 00228 cout << "SineGenerator: setDeviceSettings" << endl; 00229 #endif 00230 00231 ticpp::Iterator<ticpp::Element> elem(father->FirstChildElement(hw_fs_,true)); 00232 setSamplingRate(elem); 00233 00234 elem = father->FirstChildElement(hw_channels_,false); 00235 if(elem != elem.end()) 00236 setDeviceChannels(elem); 00237 00238 elem = father->FirstChildElement(hw_blocksize_,false); 00239 if(elem != elem.end()) 00240 setBlocks(elem); 00241 } 00242 00243 //--------------------------------------------------------------------------------------- 00244 00245 void SineGenerator::setChannelSettings(ticpp::Iterator<ticpp::Element>const &father) 00246 { 00247 #ifdef DEBUG 00248 cout << "SineGenerator: setChannelSettings" << endl; 00249 #endif 00250 00251 ticpp::Iterator<ticpp::Element> elem(father->FirstChildElement(hw_chset_sel_,false)); 00252 if (elem != elem.end()) 00253 setChannelSelection(elem); 00254 } 00255 00256 //--------------------------------------------------------------------------------------- 00257 00258 } // Namespace tobiss