$treeview $search $mathjax $extrastylesheet
otsdaq_components
v2_03_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #include "OtsUDPFirmwareCore.h" 00002 00003 #include "otsdaq-core/Macros/CoutMacros.h" 00004 #include "otsdaq-core/MessageFacility/MessageFacility.h" 00005 00006 //#include "otsdaq-core/BitManipulator/BitManipulator.h" 00007 //#include "otsdaq-components/DAQHardware/FirmwareBaseDefinitions.h" 00008 00009 #include <arpa/inet.h> 00010 #include <netinet/in.h> 00011 #include <sys/socket.h> 00012 #include <algorithm> 00013 #include <cstdlib> 00014 #include <iomanip> 00015 #include <iostream> 00016 //#include 00017 //"otsdaq-components/UserConfigurationDataFormats/FEOtsUDPFSSRInterfaceTable.h" 00018 00019 using namespace ots; 00020 00022 // ADDRESS SPACE 00023 // http://otsdaq.fnal.gov/docs/oei_address_space.html 00024 // field size (bits) 00025 #define UDP_CORE_BLOCK_ADDRESS ((uint64_t)(0x1) << 32) 00026 #define ADDR_SELF_UPPER_IP (uint64_t)(0x0) // 24 00027 #define ADDR_SELF_LOWER_IP (uint64_t)(0x1) // 8 00028 #define ADDR_SELF_MAC (uint64_t)(0x2) // 40 00029 00030 #define ADDR_CTRL_DEST_IP (uint64_t)(0x3) // 32 00031 #define ADDR_CTRL_DEST_MAC (uint64_t)(0x4) // 48 00032 #define ADDR_CTRL_DEST_PORT (uint64_t)(0x5) // 16 00033 00034 #define ADDR_DATA_DEST_IP (uint64_t)(0x6) // 32 00035 #define ADDR_DATA_DEST_MAC (uint64_t)(0x7) // 48 00036 #define ADDR_DATA_DEST_PORT (uint64_t)(0x8) // 16 00037 00038 #define ADDR_BURST_MODE (uint64_t)(0x9) // 1 00039 #define ADDR_CTRL_RESOLVE_MAC (uint64_t)(0xA) // 1 00040 #define ADDR_DATA_RESOLVE_MAC (uint64_t)(0xB) // 1 00041 #define ADDR_SELF_VERSION (uint64_t)(0x64) // 16 (read only) 00042 #define ADDR_SELF_RESET (uint64_t)(0xFFFFFFFF) // 1 (write only) 00043 00044 // end ADDRESS SPACE 00046 00047 const uint8_t OtsUDPFirmwareCore::FIFO_ADDRESS_CMD_TYPE = (1 << 3); 00048 00049 //======================================================================================================================== 00050 OtsUDPFirmwareCore::OtsUDPFirmwareCore(unsigned int version) 00051 : FrontEndFirmwareBase(version) 00052 { 00053 } 00054 00055 //======================================================================================================================== 00056 OtsUDPFirmwareCore::~OtsUDPFirmwareCore(void) {} 00057 00058 //======================================================================================================================== 00059 void OtsUDPFirmwareCore::init(void) {} 00060 00061 //======================================================================================================================== 00062 std::string OtsUDPFirmwareCore::write(char* address, char* data) 00063 { 00064 std::string buffer; 00065 writeAdvanced(buffer, address, data); 00066 return buffer; 00067 } 00068 00069 //======================================================================================================================== 00070 void OtsUDPFirmwareCore::write(std::string& buffer, 00071 char* address, 00072 char* data, 00073 bool clearBuffer) 00074 { 00075 writeAdvanced(buffer, address, data, 1 /*size*/, 0 /*options*/, clearBuffer); 00076 } 00077 00078 //======================================================================================================================== 00079 void OtsUDPFirmwareCore::write(std::string& buffer, 00080 uint32_t address, 00081 uint32_t data, 00082 bool clearBuffer) 00083 { 00084 writeAdvanced(buffer, address, data, 0 /*options*/, clearBuffer); 00085 } 00086 00087 //======================================================================================================================== 00088 void OtsUDPFirmwareCore::write(std::string& buffer, 00089 uint64_t address, 00090 uint64_t data, 00091 bool clearBuffer) 00092 { 00093 writeAdvanced(buffer, address, data, 0 /*options*/, clearBuffer); 00094 } 00095 00096 //======================================================================================================================== 00097 // OtsUDPFirmwareCore::writeAdvanced 00098 // size is in units of quad-words (8-Bytes) 00099 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::writeAdvanced(std::string& buffer, 00100 const char* address, 00101 const char* data, 00102 uint8_t size, 00103 uint8_t commandTypeOptions, 00104 bool clearBuffer) 00105 { 00106 if(size > 182) 00107 { 00108 __SS__ << "Invalid OtsUDPFirmwareCore::writeAdvanced size: " << size << std::endl; 00109 __COUT_ERR__ << "\n" << ss.str(); 00110 __SS_THROW__; 00111 } 00112 00113 if(buffer.size() + 2 + 8 + 8 * size > 2 + 8 + 8 * 182) 00114 { 00115 __SS__ << "Aborting. Buffer overflow attempt: " << buffer.size() << " + " 00116 << 2 + 8 + 8 * size << " > " << 2 + 8 + 8 * 182 << std::endl; 00117 __COUT_ERR__ << "\n" << ss.str(); 00118 __SS_THROW__; 00119 } 00120 00121 if(clearBuffer) 00122 buffer.resize(0); 00123 00124 unsigned int begin = buffer.length(); 00125 buffer.resize(buffer.length() + 2 + 8 + 8 * size, '\0'); 00126 00127 buffer[begin + 0] = 1 | commandTypeOptions; // OtsUDPFirmwareCore::writeAdvanced 00128 buffer[begin + 1] = size; //# of 64 bits words 00129 00130 std::copy_n(address, sizeof(uint64_t), &buffer[begin + 2]); 00131 for(uint8_t i = 0; i < size; ++i) 00132 std::copy_n( 00133 (char*)&data[8 * i], sizeof(uint64_t), &buffer[begin + 2 + 8 + 8 * i]); 00134 00136 /* 00137 __SS__ << "\tAdded OtsUDPFirmwareCore::writeAdvanced to Buffer:-"; 00138 for(uint32_t i=begin; i<buffer.size(); i++) 00139 { 00140 if(i==begin+2) ss << ":::"; 00141 else if(i==begin+10) ss << ":::"; 00142 ss << std::setfill('0') << std::setw(2) << std::hex << (((int16_t) buffer[i]) 00143 &0xFF) << "-" << std::dec; 00144 } 00145 ss << " added " << (buffer.size() - begin) << " to " << buffer.size(); 00146 ss << std::endl; 00147 __COUT__ << "\n" << ss.str(); 00148 */ 00149 } 00150 00151 //======================================================================================================================== 00152 // OtsUDPFirmwareCore::writeAdvanced 00153 // Note: size is required, to remove ambiguity when calling 00154 // OtsUDPFirmwareCore::writeAdvanced with data=0 00155 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::writeAdvanced(std::string& buffer, 00156 const uint64_t& address, 00157 const char* data, 00158 uint8_t size, 00159 uint8_t commandTypeOptions, 00160 bool clearBuffer) 00161 { 00162 OtsUDPFirmwareCore::writeAdvanced( 00163 buffer, (char*)&address, data, size, commandTypeOptions, clearBuffer); 00164 } 00165 00166 //======================================================================================================================== 00167 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::writeAdvanced(std::string& buffer, 00168 const uint64_t& address, 00169 const uint64_t& data, 00170 uint8_t commandTypeOptions, 00171 bool clearBuffer) 00172 { 00173 OtsUDPFirmwareCore::writeAdvanced(buffer, 00174 (char*)&address, 00175 (char*)&data, 00176 1 /*size*/, 00177 commandTypeOptions, 00178 clearBuffer); 00179 } 00180 00181 //======================================================================================================================== 00182 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::writeAdvanced( 00183 std::string& buffer, 00184 const uint64_t& address, 00185 const std::vector<uint64_t>& data, 00186 uint8_t commandTypeOptions, 00187 bool clearBuffer) 00188 { 00189 OtsUDPFirmwareCore::writeAdvanced(buffer, 00190 (char*)&address, 00191 (char*)&data[0], 00192 data.size() /*size*/, 00193 commandTypeOptions, 00194 clearBuffer); 00195 } 00196 00197 //======================================================================================================================== 00198 std::string OtsUDPFirmwareCore::read(char* address) 00199 { 00200 __COUT__ << "OTS pointer based read!! " << std::endl; 00201 std::string buffer; 00202 readAdvanced(buffer, address); 00203 return buffer; 00204 } 00205 00206 //======================================================================================================================== 00207 void OtsUDPFirmwareCore::read(std::string& buffer, char* address, bool clearBuffer) 00208 { 00209 readAdvanced(buffer, address, 1 /*size*/, 0 /*options*/, clearBuffer); 00210 } 00211 00212 //======================================================================================================================== 00213 void OtsUDPFirmwareCore::read(std::string& buffer, uint64_t address, bool clearBuffer) 00214 { 00215 readAdvanced(buffer, address, 1 /*size*/, 0 /*options*/, clearBuffer); 00216 } 00217 00218 //======================================================================================================================== 00219 void OtsUDPFirmwareCore::read(std::string& buffer, uint32_t address, bool clearBuffer) 00220 { 00221 readAdvanced(buffer, address, 1 /*size*/, 0 /*options*/, clearBuffer); 00222 } 00223 00224 //======================================================================================================================== 00225 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::readAdvanced(std::string& buffer, 00226 char* address, 00227 uint8_t size, 00228 uint8_t commandTypeOptions, 00229 bool clearBuffer) 00230 { 00231 if(size > 182) 00232 { 00233 __SS__ << "Invalid OtsUDPFirmwareCore::readAdvanced size: " << size << std::endl; 00234 __COUT_ERR__ << "\n" << ss.str(); 00235 __SS_THROW__; 00236 } 00237 00238 if(buffer.size() + 2 + 8 > 2 + 8 + 8 * 182) 00239 { 00240 __SS__ << "Aborting. Buffer overflow attempt: " << buffer.size() << " + " << 2 + 8 00241 << " > " << 2 + 8 + 8 * 182 << std::endl; 00242 __COUT_ERR__ << "\n" << ss.str(); 00243 __SS_THROW__; 00244 } 00245 00246 if(clearBuffer) 00247 buffer.resize(0); 00248 00249 unsigned int begin = buffer.length(); 00250 buffer.resize(buffer.length() + 2 + 8, '\0'); 00251 00252 buffer[begin + 0] = 00253 (uint8_t)0 | commandTypeOptions; // OtsUDPFirmwareCore::readAdvanced 00254 buffer[begin + 1] = size; //# of 64 bits words 00255 00256 // NOTE -- be wary of copy_n RAR -- it failed for me with uint32_t size 00257 std::copy_n(address, sizeof(uint64_t), &buffer[begin + 2]); 00258 00260 //__SS__ << "\tAdded OtsUDPFirmwareCore::readAdvanced to Buffer:-"; 00261 // for(uint32_t i=begin; i<buffer.size(); i++) 00262 //{ 00263 // if(i==begin+2) ss << ":::"; 00264 // else if(i==begin+10) ss << ":::"; 00265 // ss << std::setfill('0') << std::setw(2) << std::hex << (((int16_t) buffer[i]) 00266 //&0xFF) << "-" << std::dec; 00267 //} 00268 // ss << std::endl; 00269 //__COUT__ << "\n" << ss.str(); 00270 } 00271 00272 //======================================================================================================================== 00273 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::readAdvanced(std::string& buffer, 00274 const uint64_t& address, 00275 uint8_t size, 00276 uint8_t commandTypeOptions, 00277 bool clearBuffer) 00278 { 00279 OtsUDPFirmwareCore::readAdvanced( 00280 buffer, (char*)&address, size, commandTypeOptions, clearBuffer); 00281 } 00282 00283 //======================================================================================================================== 00284 void OtsUDPFirmwareCore::setDataDestination(std::string& buffer, 00285 const std::string& ipAddress, 00286 const uint16_t port, 00287 bool clearBuffer) 00288 { 00289 // put firmware in dynamic mac resolution mode for burst mode 00290 //__COUT__ << "Dynamic mac address: " << std::hex << 00291 // uint64_t(UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_RESOLVE_MAC) << std::endl; 00292 OtsUDPFirmwareCore::write(buffer, 00293 UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_RESOLVE_MAC /* addr */, 00294 1 /* data */, 00295 clearBuffer); 00296 00297 // extract ip address from string 00298 //__COUT__ << "IP Address = " << ipAddress << std::endl; 00299 uint64_t ip = 0; 00300 int ipArr[4]; 00301 sscanf(ipAddress.c_str(), "%d.%d.%d.%d", &ipArr[3], &ipArr[2], &ipArr[1], &ipArr[0]); 00302 for(int i = 0; i < 4; ++i) 00303 (((char*)&ip)[i]) += ipArr[i] & 0x0FF; 00304 00305 writeDataDestinationIP(buffer, ip, false /*clearBuffer*/); 00306 writeDataDestinationPort(buffer, port, false /*clearBuffer*/); 00307 } 00308 00309 //======================================================================================================================== 00310 void OtsUDPFirmwareCore::setControlDestination(std::string& buffer, 00311 const std::string& ipAddress, 00312 const uint16_t port) 00313 { 00314 // put firmware in dynamic mac resolution mode for burst mode 00315 OtsUDPFirmwareCore::writeAdvanced( 00316 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_RESOLVE_MAC /* addr */, 1 /* data */); 00317 00318 // extract ip address from string 00319 __COUT__ << "ipAddress = " << ipAddress << std::endl; 00320 uint64_t ip = 0; 00321 int ipArr[4]; 00322 sscanf(ipAddress.c_str(), "%d.%d.%d.%d", &ipArr[3], &ipArr[2], &ipArr[1], &ipArr[0]); 00323 for(int i = 0; i < 4; ++i) 00324 (((char*)&ip)[i]) += ipArr[i] & 0x0FF; 00325 00326 writeControlDestinationIP(buffer, ip); 00327 writeControlDestinationPort(buffer, port); 00328 } 00329 00330 //======================================================================================================================== 00331 // return data lower 32 bits 00332 uint32_t OtsUDPFirmwareCore::createRegisterFromValue(std::string& readBuffer, 00333 std::string& receivedValue) 00334 { 00335 uint32_t retVal = *((uint32_t*)(&receivedValue[2])); 00336 00337 // for(unsigned int i=0;i<receivedValue.size();++i) 00338 // __COUT__ << std::hex << (int)receivedValue[i] << std::dec << std::endl; 00339 //__COUT__ << "Register value: 0x" << std::hex << retVal << std::dec << std::endl; 00340 return retVal; 00341 } 00342 00343 //======================================================================================================================== 00344 void OtsUDPFirmwareCore::writeDataDestinationIP(std::string& buffer, 00345 const uint64_t value, 00346 bool clearBuffer) 00347 { 00348 OtsUDPFirmwareCore::writeAdvanced( 00349 buffer, 00350 UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_IP /* addr */, 00351 value /* data */, 00352 0 /*options*/, 00353 clearBuffer); 00354 } 00355 00356 //======================================================================================================================== 00357 void OtsUDPFirmwareCore::writeDataDestinationMAC(std::string& buffer, 00358 const uint64_t value, 00359 bool clearBuffer) 00360 { 00361 OtsUDPFirmwareCore::writeAdvanced( 00362 buffer, 00363 UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_MAC /* addr */, 00364 value /* data */, 00365 0 /*options*/, 00366 clearBuffer); 00367 } 00368 00369 //======================================================================================================================== 00370 void OtsUDPFirmwareCore::writeDataDestinationPort(std::string& buffer, 00371 const uint64_t value, 00372 bool clearBuffer) 00373 { 00374 OtsUDPFirmwareCore::writeAdvanced( 00375 buffer, 00376 UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_PORT /* addr */, 00377 value /* data */, 00378 0 /*options*/, 00379 clearBuffer); 00380 } 00381 00382 //======================================================================================================================== 00383 void OtsUDPFirmwareCore::readDataDestinationIP(std::string& buffer) 00384 { 00385 OtsUDPFirmwareCore::readAdvanced( 00386 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_IP /* addr */); 00387 } 00388 00389 //======================================================================================================================== 00390 void OtsUDPFirmwareCore::readDataDestinationMAC(std::string& buffer) 00391 { 00392 OtsUDPFirmwareCore::readAdvanced( 00393 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_MAC /* addr */); 00394 } 00395 00396 //======================================================================================================================== 00397 void OtsUDPFirmwareCore::readDataDestinationPort(std::string& buffer) 00398 { 00399 OtsUDPFirmwareCore::readAdvanced( 00400 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_PORT /* addr */); 00401 } 00402 00403 //======================================================================================================================== 00404 void OtsUDPFirmwareCore::writeControlDestinationIP(std::string& buffer, 00405 const uint64_t value) 00406 { 00407 OtsUDPFirmwareCore::writeAdvanced( 00408 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_IP /* addr */, value /* data */); 00409 } 00410 00411 //======================================================================================================================== 00412 void OtsUDPFirmwareCore::writeControlDestinationMAC(std::string& buffer, 00413 const uint64_t value) 00414 { 00415 OtsUDPFirmwareCore::writeAdvanced( 00416 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_MAC /* addr */, value /* data */); 00417 } 00418 00419 //======================================================================================================================== 00420 void OtsUDPFirmwareCore::writeControlDestinationPort(std::string& buffer, 00421 const uint64_t value) 00422 { 00423 OtsUDPFirmwareCore::writeAdvanced( 00424 buffer, 00425 UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_PORT /* addr */, 00426 value /* data */); 00427 } 00428 00429 //======================================================================================================================== 00430 void OtsUDPFirmwareCore::readControlDestinationIP(std::string& buffer) 00431 { 00432 OtsUDPFirmwareCore::readAdvanced( 00433 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_IP /* addr */); 00434 } 00435 00436 //======================================================================================================================== 00437 void OtsUDPFirmwareCore::readControlDestinationMAC(std::string& buffer) 00438 { 00439 OtsUDPFirmwareCore::readAdvanced( 00440 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_MAC /* addr */); 00441 } 00442 00443 //======================================================================================================================== 00444 void OtsUDPFirmwareCore::readControlDestinationPort(std::string& buffer) 00445 { 00446 OtsUDPFirmwareCore::readAdvanced( 00447 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_PORT /* addr */); 00448 } 00449 00450 //======================================================================================================================== 00451 void OtsUDPFirmwareCore::readUDPFirmwareVersion(std::string& buffer) 00452 { 00453 OtsUDPFirmwareCore::readAdvanced( 00454 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_SELF_VERSION /* addr */); 00455 } 00456 00457 //======================================================================================================================== 00458 void OtsUDPFirmwareCore::softEthernetReset(std::string& buffer) 00459 { 00460 OtsUDPFirmwareCore::writeAdvanced( 00461 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_SELF_RESET /* addr */, 0x3 /* data */); 00462 } 00463 00464 //======================================================================================================================== 00465 void OtsUDPFirmwareCore::hardEthernetReset(std::string& buffer) 00466 { 00467 OtsUDPFirmwareCore::writeAdvanced( 00468 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_SELF_RESET /* addr */, 0x1 /* data */); 00469 } 00470 00471 //======================================================================================================================== 00472 void OtsUDPFirmwareCore::clearEthernetReset(std::string& buffer) 00473 { 00474 OtsUDPFirmwareCore::writeAdvanced( 00475 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_SELF_RESET /* addr */, 0 /* data */); 00476 } 00477 00478 //======================================================================================================================== 00479 void OtsUDPFirmwareCore::startBurst(std::string& buffer) 00480 { 00481 __COUT__ << std::endl; 00482 OtsUDPFirmwareCore::writeAdvanced( 00483 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_BURST_MODE /* addr */, 1 /* data */); 00484 } 00485 00486 //======================================================================================================================== 00487 void OtsUDPFirmwareCore::stopBurst(std::string& buffer) 00488 { 00489 __COUT__ << std::endl; 00490 OtsUDPFirmwareCore::writeAdvanced( 00491 buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_BURST_MODE /* addr */, 0 /* data */); 00492 }