$treeview $search $mathjax $extrastylesheet
otsdaq_components
v2_03_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #include "otsdaq-components/DAQHardware/OtsUDPHardware.h" 00002 #include <iomanip> 00003 #include <iostream> 00004 #include "otsdaq-core/Macros/CoutMacros.h" 00005 #include "otsdaq-core/MessageFacility/MessageFacility.h" 00006 00007 using namespace ots; 00008 00009 //======================================================================================================================== 00010 // This one is often (e.g. FENIMPlusInterface) called by FEs inheriting OtsUDPHardware 00011 OtsUDPHardware::OtsUDPHardware(std::string boardIPAddress, 00012 unsigned int boardPort, 00013 unsigned int version, 00014 bool verbose) 00015 : // Socket () default constructor 00016 FrontEndHardwareBase(version) 00017 , OtsUDPBoard_(boardIPAddress, boardPort) 00018 , verbose_(verbose) 00019 { 00020 Socket::initialize(); 00021 00022 // char msg[100]; 00023 // sprintf(msg,"_%d",getPort()); 00024 // std::string fn = "/tmp/new_udp_chk" + std::string(msg) + ".dat"; 00025 // FILE *fp = fopen(fn.c_str(),"w"); 00026 // if(fp) fclose(fp); 00027 // __COUT__ << fn << std::endl; 00028 } 00029 00030 //======================================================================================================================== 00031 OtsUDPHardware::OtsUDPHardware(std::string hostIPAddress, 00032 unsigned int hostPort, 00033 std::string OtsUDPHardwareIPAddress, 00034 unsigned int OtsUDPHardwarePort, 00035 unsigned int version, 00036 bool verbose) 00037 : Socket(hostIPAddress, hostPort) 00038 , FrontEndHardwareBase(version) 00039 , OtsUDPBoard_(OtsUDPHardwareIPAddress, OtsUDPHardwarePort) 00040 , verbose_(verbose) 00041 { 00042 Socket::initialize(); 00043 00044 __COUT__ << "Socket for hardware is initialized at IP:Port " 00045 << OtsUDPBoard_.getIPAddress() << ":" << OtsUDPBoard_.getPort() << __E__; 00046 00047 // char msg[100]; 00048 // sprintf(msg,"_%d",getPort()); 00049 // std::string fn = "/tmp/new_udp_chk" + std::string(msg) + ".dat"; 00050 // FILE *fp = fopen(fn.c_str(),"w"); 00051 // if(fp) fclose(fp); 00052 // __COUT__ << fn << std::endl; 00053 } 00054 00055 //======================================================================================================================== 00056 OtsUDPHardware::~OtsUDPHardware(void) {} 00057 00058 //======================================================================================================================== 00059 void OtsUDPHardware::write(const std::string& sendBuffer) throw(std::runtime_error) try 00060 { 00061 // char msg[100]; 00062 // sprintf(msg,"_%d",getPort()); 00063 // std::string fn = "/tmp/new_udp_chk" + std::string(msg) + ".dat"; 00064 // FILE *fp = fopen(fn.c_str(),"a"); 00065 // __COUT__ << fn << std::endl; 00066 00067 // 00068 // if(fp) //debug 00069 // { 00070 // std::stringstream ss; 00071 // ss << "\t"; 00072 // uint32_t begin = 0; 00073 // for(uint32_t i=begin; i<sendBuffer.size(); i++) 00074 // { 00075 // if(i==begin+2) ss << ":::"; 00076 // else if(i==begin+10) ss << ":::"; 00077 // ss << std::setfill('0') << std::setw(2) << std::hex << (((int16_t) 00078 // sendBuffer[i]) &0xFF) << "-" << std::dec; 00079 // } 00080 // ss << std::endl; 00081 // fprintf(fp,"%s",ss.str().c_str()); 00082 // } 00083 // if(fp) fclose(fp); 00084 00085 if(TransceiverSocket::send(OtsUDPBoard_, sendBuffer, verbose_) < 0) 00086 { 00087 __SS__ << "Write failed to hardware at IP:Port " << OtsUDPBoard_.getIPAddress() 00088 << ":" << OtsUDPBoard_.getPort() << __E__; 00089 __SS_THROW__; 00090 } 00091 } 00092 catch(std::runtime_error& e) 00093 { 00094 throw; 00095 } 00096 catch(...) 00097 { 00098 __SS__ << "Unrecognized exception caught!" << std::endl; 00099 __SS_THROW__; 00100 } 00101 00102 //======================================================================================================================== 00103 void OtsUDPHardware::write(const std::vector<std::string>& sendBuffer) throw( 00104 std::runtime_error) 00105 { 00106 for(const auto& it : sendBuffer) 00107 { 00108 // char msg[100]; 00109 // sprintf(msg,"_%d",getPort()); 00110 // std::string fn = "/tmp/new_udp_chk" + std::string(msg) + ".dat"; 00111 // FILE *fp = fopen(fn.c_str(),"a"); 00112 // __COUT__ << fn << std::endl; 00113 00114 // if(fp) //debug 00115 // { 00116 // std::stringstream ss; 00117 // ss << "\t"; 00118 // uint32_t begin = 0; 00119 // for(uint32_t i=begin; i<it.size(); i++) 00120 // { 00121 // if(i==begin+2) ss << ":::"; 00122 // else if(i==begin+10) ss << ":::"; 00123 // ss << std::setfill('0') << std::setw(2) << std::hex << (((const 00124 // int16_t) it[i]) &0xFF) << "-" << std::dec; 00125 // } 00126 // ss << std::endl; 00127 // fprintf(fp,"%s",ss.str().c_str()); 00128 // } 00129 // if(fp) fclose(fp); 00130 00131 write(it); 00132 } 00133 } 00134 00135 //======================================================================================================================== 00136 void OtsUDPHardware::writeAndAcknowledge(const std::string& buffer, 00137 int timeoutSeconds) throw(std::runtime_error) try 00138 { 00139 // char msg[100]; 00140 // sprintf(msg,"_%d",getPort()); 00141 // std::string fn = "/tmp/new_udp_chk" + std::string(msg) + ".dat"; 00142 // FILE *fp = fopen(fn.c_str(),"a"); 00143 // __COUT__ << fn << std::endl; 00144 00145 // if(fp) //debug 00146 // { 00147 // std::stringstream ss; 00148 // ss << "\tack "; 00149 // uint32_t begin = 0; 00150 // for(uint32_t i=begin; i<buffer.size(); i++) 00151 // { 00152 // if(i==begin+2) ss << ":::"; 00153 // else if(i==begin+10) ss << ":::"; 00154 // ss << std::setfill('0') << std::setw(2) << std::hex << (((int16_t) 00155 // buffer[i]) &0xFF) << "-" << std::dec; 00156 // } 00157 // ss << std::endl; 00158 // fprintf(fp,"%s",ss.str().c_str()); 00159 // } 00160 // if(fp) fclose(fp); 00161 00162 // __COUT__ << std::endl; 00163 // for(auto& b: buffer) 00164 // { 00165 // __COUT__ << std::hex << (uint16_t)b << std::dec << std::endl; 00166 // } 00167 TransceiverSocket::send(OtsUDPBoard_, buffer, verbose_); 00168 // acknowledgment_.clear(); 00169 00170 if(timeoutSeconds < 0) // use default timeout 00171 timeoutSeconds = 5; 00172 00173 if(TransceiverSocket::receive(acknowledgment_, timeoutSeconds) < 0) 00174 { 00175 __SS__ << "writeAndAcknowledge failed from hardware at IP:Port " 00176 << OtsUDPBoard_.getIPAddress() << ":" << OtsUDPBoard_.getPort() 00177 << ". Timeout period of " << timeoutSeconds 00178 << " seconds reached without response." << std::endl; 00179 __COUT_ERR__ << "\n" << ss.str() << std::endl; 00180 __SS_THROW__; 00181 } 00182 00183 // __COUT__ << "Acknowledgment size: " << acknowledgment_.size() << std::endl; 00184 // for(unsigned int i=0; i< acknowledgment_.size(); i++) 00185 // { 00186 // if(i%24 == 0) 00187 // __COUT__ << i << "("<< (unsigned int)acknowledgment_[i] << ")-" << std::endl; 00188 // } 00189 // 00190 00191 // Check First Byte: 00192 // (https://docs.google.com/document/d/1i3Z07n8Jq78NwgUFdjAv2sLGhH4rWjHeYEScAWBzSyw/edit?usp=sharing) 00193 // bits 2:0 = Packet Type (0: Read, 1: First in Burst, 2: Burst Middle, 3: Last in 00194 // Burst, 4: Read Ack, 5: Write Ack, 6: Burst Start Ack, 7: Burst Stop Ack) bit 3 00195 // = ack of no address increment op bit 4 = err detected in protocol since reset 00196 // bit 5 = rx overflow since reset 00197 // bit 6 = crc err flag 00198 // bit 7 = crc err detected 00199 00200 if((acknowledgment_[0] >> 4)) 00201 { 00202 __SS__ << "Error in OTS protocol encountered! " << std::setfill('0') 00203 << std::setw(2) << std::hex << (((int16_t)acknowledgment_[0]) & 0xff) 00204 << "-" << std::dec << __E__; 00205 __SS_THROW__; 00206 } 00207 } 00208 catch(std::runtime_error& e) 00209 { 00210 throw; 00211 } 00212 catch(...) 00213 { 00214 __SS__ << "Unrecognized exception caught!" << std::endl; 00215 __COUT_ERR__ << "\n" << ss.str() << std::endl; 00216 __SS_THROW__; 00217 } 00218 00219 //======================================================================================================================== 00220 void OtsUDPHardware::writeAndAcknowledge(const std::vector<std::string>& buffer, 00221 int timeoutSeconds) throw(std::runtime_error) 00222 { 00223 for(const auto& it : buffer) 00224 { 00225 // char msg[100]; 00226 // sprintf(msg,"_%d",getPort()); 00227 // std::string fn = "/tmp/new_udp_chk" + std::string(msg) + ".dat"; 00228 // FILE *fp = fopen(fn.c_str(),"a"); 00229 // __COUT__ << fn << std::endl; 00230 00231 // if(fp) //debug 00232 // { 00233 // std::stringstream ss; 00234 // ss << "\tack "; 00235 // uint32_t begin = 0; 00236 // for(uint32_t i=begin; i<it.size(); i++) 00237 // { 00238 // if(i==begin+2) ss << ":::"; 00239 // else if(i==begin+10) ss << ":::"; 00240 // ss << std::setfill('0') << std::setw(2) << std::hex << (((const 00241 // int16_t) it[i]) &0xFF) << "-" << std::dec; 00242 // } 00243 // ss << std::endl; 00244 // fprintf(fp,"%s",ss.str().c_str()); 00245 // } 00246 // if(fp) fclose(fp); 00247 00248 writeAndAcknowledge(it); 00249 } 00250 } 00251 00252 //======================================================================================================================== 00253 // return -1 on failure 00254 void OtsUDPHardware::read(const std::string& sendBuffer, 00255 std::string& receiveBuffer, 00256 int timeoutSeconds) throw(std::runtime_error) try 00257 { 00258 { // clear packets so that read matches! 00259 int clearedPackets = OtsUDPHardware::clearReadSocket(); 00260 if(clearedPackets) 00261 __COUT__ << "Cleared receive socket buffer: " << clearedPackets 00262 << " packets cleared." << std::endl; 00263 } 00264 00265 __COUT__ << "Sending" << std::endl; 00266 TransceiverSocket::send(OtsUDPBoard_, sendBuffer, verbose_); 00267 00268 if(timeoutSeconds < 0) // use default timeout 00269 timeoutSeconds = 5; 00270 00271 __COUT__ << "Receiving" << std::endl; 00272 if(TransceiverSocket::receive( 00273 receiveBuffer, timeoutSeconds, 0 /*timeoutUSeconds*/, verbose_) < 0) 00274 { 00275 __SS__ << "Read failed from hardware at IP : Port " << OtsUDPBoard_.getIPAddress() 00276 << " : " << OtsUDPBoard_.getPort() << ". Timeout period of " 00277 << timeoutSeconds << " seconds reached without response." << __E__; 00278 __SS_THROW__; 00279 } 00280 00281 //__COUT__ << "Received Message: "; 00282 // for(uint32_t i=0; i<receiveBuffer.size(); i++) 00283 // std::cout << std::setfill('0') << std::setw(2) << std::hex << (((int16_t) 00284 // receiveBuffer[i]) &0xff) << "-" << std::dec; std::cout << std::endl; 00285 00286 // Check First Byte: 00287 // (https://docs.google.com/document/d/1i3Z07n8Jq78NwgUFdjAv2sLGhH4rWjHeYEScAWBzSyw/edit?usp=sharing) 00288 // bits 2:0 = Packet Type (0: Read, 1: First in Burst, 2: Burst Middle, 3: Last in 00289 // Burst, 4: Read Ack, 5: Write Ack, 6: Burst Start Ack, 7: Burst Stop Ack) bit 3 00290 // = ack of no address increment op bit 4 = err detected in protocol since reset 00291 // bit 5 = rx overflow since reset 00292 // bit 6 = crc err flag 00293 // bit 7 = crc err detected 00294 00295 if((receiveBuffer[0] >> 5)) // FIXME?? also consider bit 4? 00296 { 00297 __SS__ << "Error in OTS protocol encountered! " << std::setfill('0') 00298 << std::setw(2) << std::hex << (((int16_t)receiveBuffer[0]) & 0xff) << "-" 00299 << std::dec << __E__; 00300 //__SS_THROW__; 00301 } 00302 } 00303 catch(std::runtime_error& e) 00304 { 00305 throw; 00306 } 00307 catch(...) 00308 { 00309 __SS__ << "Unrecognized exception caught!" << std::endl; 00310 __SS_THROW__; 00311 } 00312 00313 //======================================================================================================================== 00314 void OtsUDPHardware::read(const std::vector<std::string>& sendBuffers, 00315 std::vector<std::string>& receiveBuffers, 00316 int timeoutSeconds) throw(std::runtime_error) 00317 { 00318 receiveBuffers.resize(sendBuffers.size()); 00319 auto receiveBufferIterator = receiveBuffers.begin(); 00320 for(const auto& sendBuffer : sendBuffers) 00321 read(sendBuffer, *(receiveBufferIterator++)); 00322 } 00323 00324 //======================================================================================================================== 00325 void OtsUDPHardware::read(const std::string& sendBuffer, 00326 uint64_t& receiveQuadWord, 00327 int timeoutSeconds) throw(std::runtime_error) 00328 { 00329 std::string receiveBuffer; 00330 read(sendBuffer, receiveBuffer); 00331 00332 // force response to be only one quad word 00333 if(receiveBuffer.length() != 10) 00334 { 00335 __SS__ << "Read uint64_t quad-word failed. Invalid size of received buffer: " 00336 << receiveBuffer.length() << " != " << 10 << std::endl; 00337 __SS_THROW__; 00338 } 00339 // copy_n does not work!! alert?! it only copies the first byte? 00340 // std::copy_n((char *)&receiveBuffer[2],sizeof(uint64_t),&receiveQuadWord); 00341 // 00342 // __COUT__ << "receiveQuadWord all = 0x" << std::hex << 00343 // receiveQuadWord << std::dec << std::endl; 00344 00345 receiveQuadWord = *((uint64_t*)&receiveBuffer[2]); 00346 // //memcpy((char *)&receiveBuffer[2],sizeof(uint64_t),&receiveQuadWord); 00347 // __COUT__ << "receiveQuadWord all = 0x" << std::hex << 00348 // receiveQuadWord << std::dec << std::endl; 00349 } 00350 00351 //======================================================================================================================== 00352 void OtsUDPHardware::read(const std::string& sendBuffer, 00353 std::vector<uint64_t>& receiveQuadWords, 00354 int timeoutSeconds) throw(std::runtime_error) 00355 { 00356 receiveQuadWords.resize(0); // clear 00357 00358 std::string receiveBuffer; 00359 read(sendBuffer, receiveBuffer); 00360 00361 // force response to be only integer quad words 00362 if((receiveBuffer.length() - 2) % 8 != 0) 00363 { 00364 __SS__ << "Read vector of uint64_t quad-word failed. Invalid size of received " 00365 "buffer: (" 00366 << receiveBuffer.length() << " - 2) % 8 != 0" << std::endl; 00367 __SS_THROW__; 00368 } 00369 00370 for(unsigned int i = 2; i < receiveBuffer.length(); i += 8) 00371 { 00372 receiveQuadWords.push_back(uint64_t()); 00373 00374 // copy_n does not work!! alert?! it only copies the first byte? 00375 // std::copy_n((char 00376 // *)&receiveBuffer[i],sizeof(uint64_t),&receiveQuadWords[receiveQuadWords.size()-1]); 00377 receiveQuadWords[receiveQuadWords.size() - 1] = *((uint64_t*)&receiveBuffer[i]); 00378 } 00379 } 00380 00381 //======================================================================================================================== 00382 void OtsUDPHardware::read(const std::vector<std::string>& sendBuffers, 00383 std::vector<std::vector<uint64_t> >& receiveQuadWordsVector, 00384 int timeoutSeconds) throw(std::runtime_error) 00385 { 00386 receiveQuadWordsVector.resize( 00387 sendBuffers.size()); // create a return vector for each send buffer 00388 00389 std::string receiveBuffer; 00390 00391 // for each send buffere 00392 for(unsigned int b = 0; b < sendBuffers.size(); ++b) 00393 { 00394 receiveQuadWordsVector[b].resize(0); // clear 00395 00396 read(sendBuffers[b], receiveBuffer); 00397 00398 // force response to be only integer quad words 00399 if((receiveBuffer.length() - 2) % 8 != 0) 00400 { 00401 __SS__ << "Read vector of uint64_t quad-word failed. Invalid size of " 00402 "received buffer: (" 00403 << receiveBuffer.length() << " - 2) % 8 != 0" << std::endl; 00404 __SS_THROW__; 00405 } 00406 00407 // copy to uint64_t's 00408 for(unsigned int i = 2; i < receiveBuffer.length(); i += 8) 00409 { 00410 receiveQuadWordsVector[b].push_back(uint64_t()); 00411 std::copy_n((char*)&receiveBuffer[i], 00412 sizeof(uint64_t), 00413 &receiveQuadWordsVector[b][receiveQuadWordsVector[b].size() - 1]); 00414 } 00415 } 00416 } 00417 00418 //======================================================================================================================== 00419 // clearReadSocket 00420 // 00421 // flushes read socket. 00422 // 00423 // reads from read socket until timeout is reached (remove stale packets) 00424 // returns count of packets that were cleared 00425 int OtsUDPHardware::clearReadSocket() 00426 { 00427 std::string dummerReceiveBuffer; 00428 int cnt = 0; 00429 00430 // receive with no timeout 00431 try 00432 { 00433 while(TransceiverSocket::receive(dummerReceiveBuffer, 00434 0 /*timeoutSeconds*/, 00435 0 /*timeoutUSeconds*/, 00436 false /*verbose*/) >= 0) 00437 ++cnt; 00438 } 00439 catch(...) 00440 { 00441 // ignore exceptions... assume due to there be nothing to read 00442 __COUT__ << "I am crashing while trying to read the socket...strange!" 00443 << std::endl; 00444 } 00445 return cnt; 00446 }