00001 #include "base/Board.h"
00002
00003 #include <stdio.h>
00004 #include <stdarg.h>
00005 #include <string.h>
00006
00007
00009
00010 const char* base::roleToString(base::ClientRole role)
00011 {
00012 switch (role) {
00013 case roleNone: return 0;
00014 case roleObserver: return "Observer";
00015 case roleControl: return "Control";
00016 case roleDAQ: return "DAQ";
00017 }
00018 return 0;
00019 }
00020
00021
00023
00024 base::ClientRole base::defineClientRole(const char* name, base::ClientRole dflt)
00025 {
00026 if ((name==0) || (strlen(name)==0)) return dflt;
00027 if (strcmp(name,"Observer")==0) return roleObserver;
00028 if (strcmp(name,"Control")==0) return roleControl;
00029 if (strcmp(name,"DAQ")==0) return roleDAQ;
00030 return dflt;
00031 }
00032
00033
00034
00035 base::Board::Board() :
00036 fBrdFactory(0),
00037 fDefaultTimeout(2.),
00038 fVerbosity(0),
00039 fOperTrace(1),
00040 fRole(roleNone),
00041 fBrdNumber(0)
00042 {
00043 }
00044
00045 base::Board::~Board()
00046 {
00047 }
00048
00049
00051
00064 void base::Board::Debug(int lvl, const char *fmt, ...)
00065 {
00066 if (!fmt || (lvl>getVerbosity())) return;
00067
00068 va_list args;
00069 va_start(args, fmt);
00070
00071 int result(128), length(128);
00072 char *buffer = 0;
00073 while (result==length) {
00074 if (buffer) delete [] buffer;
00075 length *= 2;
00076 buffer = new char [length + 1];
00077 memset(buffer, 0, length + 1);
00078 result = vsnprintf(buffer, length, fmt, args);
00079 if (result<0) break;
00080 }
00081
00082 if (fBrdFactory)
00083 fBrdFactory->ShowDebug(lvl, buffer);
00084 else
00085 fprintf(lvl<0 ? stderr : stdout, "%s\n", buffer);
00086
00087 delete [] buffer;
00088 va_end(args);
00089 }
00090
00091
00092
00093
00095
00103 void base::Board::traceOper(OperList& lst, int rc)
00104 {
00105 if (fOperTrace == 0) return;
00106 if (fOperTrace == 1 && rc != kOperNetworkErr) return;
00107 if (fOperTrace == 2 && rc == 0) return;
00108
00109 for (int i=0; i<lst.number(); i++) {
00110 const char* aname = findRegNameByAddress(lst.oper(i).addr);
00111 if (aname==0) aname = "???";
00112
00113 if (lst.number() == 1) {
00114 Debug(0, "%3s (%u,%08x %-27s) %s 0x%08x %10d %s",
00115 (lst.oper(i).isput ? "put" : "get"),
00116 GetBoardId(), lst.oper(i).addr, aname,
00117 (lst.oper(i).isput) ? "<-" : "->",
00118 lst.oper(i).value, lst.oper(i).value,
00119 (rc == 0) ? "ok" : "FAIL");
00120
00121 } else {
00122 const char* stat = "";
00123 if (i == lst.number()-1) stat = (rc == 0) ? "ok" : "FAIL";
00124 Debug(0, "op[%02d](%u,%08x %-27s) %s 0x%08x %10d %s",
00125 i, GetBoardId(), lst.oper(i).addr, aname,
00126 (lst.oper(i).isput ? "<-" : "->"),
00127 lst.oper(i).value, lst.oper(i).value, stat);
00128 }
00129
00130 if (rc != 0) {
00131 std::string str = operErrToString(rc);
00132 Debug(0, " %s", str.c_str());
00133 }
00134 }
00135 }
00136
00137 int base::Board::operGen(bool* isput,
00138 uint32_t* addr,
00139 uint32_t* value,
00140 int num,
00141 double tmout)
00142 {
00143 OperList lst(num, isput, addr, value);
00144
00145 int res = operGen(lst, tmout);
00146
00147 for (int n=0;n<num;n++)
00148 if (!isput[n]) value[n] = lst.oper(n).value;
00149
00150 return res;
00151 }
00152
00153
00154 int base::Board::put(uint32_t addr, uint32_t value, double tmout)
00155 {
00156 bool isput = true;
00157
00158 return operGen(&isput, &addr, &value, 1, tmout);
00159 }
00160
00161 int base::Board::get(uint32_t addr, uint32_t& value, double tmout)
00162 {
00163 bool isput = false;
00164
00165 return operGen(&isput, &addr, &value, 1, tmout);
00166 }
00167
00168
00169
00171
00183 int base::Board::operPP(uint32_t addr0, uint32_t val0p,
00184 uint32_t addr1, uint32_t val1p,
00185 double tmout)
00186 {
00187 bool isput[2];
00188 uint32_t addr[2];
00189 uint32_t data[2];
00190
00191 isput[0] = true; addr[0] = addr0; data[0] = val0p;
00192 isput[1] = true; addr[1] = addr1; data[1] = val1p;
00193
00194 int rc = operGen(isput, addr, data, 2, tmout);
00195 return rc;
00196 }
00197
00198
00200
00212 int base::Board::operPG(uint32_t addr0, uint32_t val0p,
00213 uint32_t addr1, uint32_t& val1g,
00214 double tmout)
00215 {
00216 bool isput[2];
00217 uint32_t addr[2];
00218 uint32_t data[2];
00219
00220 isput[0] = true; addr[0] = addr0; data[0] = val0p;
00221 isput[1] = false; addr[1] = addr1;
00222
00223 int rc = operGen(isput, addr, data, 2, tmout);
00224 val1g = data[1];
00225 return rc;
00226 }
00227
00228
00230
00244 int base::Board::operPPP(uint32_t addr0, uint32_t val0p,
00245 uint32_t addr1, uint32_t val1p,
00246 uint32_t addr2, uint32_t val2p,
00247 double tmout)
00248 {
00249 bool isput[3];
00250 uint32_t addr[3];
00251 uint32_t data[3];
00252
00253 isput[0] = true; addr[0] = addr0; data[0] = val0p;
00254 isput[1] = true; addr[1] = addr1; data[1] = val1p;
00255 isput[2] = true; addr[2] = addr2; data[2] = val2p;
00256
00257 int rc = operGen(isput, addr, data, 3, tmout);
00258 return rc;
00259 }
00260
00261
00263
00277 int base::Board::operGGG(uint32_t addr0, uint32_t& val0p,
00278 uint32_t addr1, uint32_t& val1p,
00279 uint32_t addr2, uint32_t& val2p,
00280 double tmout)
00281 {
00282 bool isput[3];
00283 uint32_t addr[3];
00284 uint32_t data[3];
00285
00286 isput[0] = false; addr[0] = addr0;
00287 isput[1] = false; addr[1] = addr1;
00288 isput[2] = false; addr[2] = addr2;
00289
00290 int rc = operGen(isput, addr, data, 3, tmout);
00291
00292 val0p = data[0];
00293 val1p = data[1];
00294 val2p = data[2];
00295
00296 return rc;
00297 }
00298
00299
00301
00317 int base::Board::operPPPP(uint32_t addr0, uint32_t val0p,
00318 uint32_t addr1, uint32_t val1p,
00319 uint32_t addr2, uint32_t val2p,
00320 uint32_t addr3, uint32_t val3p,
00321 double tmout)
00322 {
00323 bool isput[4];
00324 uint32_t addr[4];
00325 uint32_t data[4];
00326
00327 isput[0] = true; addr[0] = addr0; data[0] = val0p;
00328 isput[1] = true; addr[1] = addr1; data[1] = val1p;
00329 isput[2] = true; addr[2] = addr2; data[2] = val2p;
00330 isput[3] = true; addr[3] = addr3; data[3] = val3p;
00331
00332 int rc = operGen(isput, addr, data, 4, tmout);
00333 return rc;
00334 }
00335
00336
00338
00343 const char* base::Board::operErrCodeName(int rc)
00344 {
00345 switch(operErrCode(rc)) {
00346 case kOperSuccess: return "success";
00347 case kOperAddrErr: return "invalid address";
00348 case kOperValueErr: return "value not allowed";
00349 case kOperStateErr: return "operation not allowed";
00350 case kOperNetworkErr: return "communication error";
00351 case kOperVerifyErr: return "readback verify error";
00352 case kOperBusErr: return "secondary bus error";
00353 }
00354 return "";
00355 }
00356
00357
00359
00376 std::string base::Board::operErrToString(int rc)
00377 {
00378 char buf[32];
00379 if (rc <0) {
00380 snprintf(buf, sizeof(buf), "rc = %d", rc);
00381 return std::string(buf);
00382 }
00383
00384 snprintf(buf, sizeof(buf), "rc = %4d,%2d -> ",
00385 operErrIndex(rc), operErrCode(rc));
00386 std::string str(buf);
00387 return str+operErrCodeName(rc);
00388 }
00389
00390
00391
00393
00399 void base::Board::addRegAddrMapping(const char* name, uint32_t addr)
00400 {
00401 std::string sname(name);
00402 fMapName2Addr[sname] = addr;
00403 fMapAddr2Name[addr] = sname;
00404 }
00405
00406
00408
00417 uint32_t base::Board::findRegAddressByName(const char* name)
00418 {
00419 mapn2a_t::iterator it = fMapName2Addr.find(std::string(name));
00420 if (it != fMapName2Addr.end())
00421 return it->second;
00422 return kAddrError;
00423 }
00424
00425
00426
00428
00436 const char* base::Board::findRegNameByAddress(uint32_t addr)
00437 {
00438 if (addr==kAddrError) return 0;
00439 mapa2n_t::iterator it = fMapAddr2Name.find(addr);
00440 if (it != fMapAddr2Name.end())
00441 return it->second.c_str();
00442 return 0;
00443 }
00444
00445
00446
00447 void base::Board::printRegAddressMap(std::ostream& os, bool byname)
00448 {
00449 char sbuf[1000];
00450
00451 if (byname) {
00452 for (mapn2a_t::iterator it=fMapName2Addr.begin(); it!=fMapName2Addr.end(); it++) {
00453 snprintf(sbuf, sizeof(sbuf), "0x08x : %s", (unsigned) it->second, (const char*) (it->first.c_str()));
00454 os << sbuf << std::endl;
00455 }
00456 } else {
00457 for (mapa2n_t::iterator it=fMapAddr2Name.begin(); it!=fMapAddr2Name.end(); it++) {
00458 snprintf(sbuf, sizeof(sbuf), "0x08x : %s", (unsigned) it->first, (const char*) (it->second.c_str()));
00459 os << sbuf << std::endl;
00460 }
00461 }
00462 }
00463
00464
00465 void base::Board::fillRegAddrNames(std::list<std::string>& lst)
00466 {
00467 for (mapn2a_t::iterator it=fMapName2Addr.begin(); it!=fMapName2Addr.end(); it++)
00468 lst.push_back(it->first);
00469 }
00470
00471
00472
00473
00475
00476 const char* base::Board::versionToString(uint32_t ver)
00477 {
00478 static char sbuf[100];
00479 snprintf(sbuf, sizeof(sbuf), "%u.%u.%u.%u",
00480 (ver >> 24),
00481 (ver >> 16) & 0xff,
00482 (ver >> 8) & 0xff,
00483 ver & 0xff);
00484 return sbuf;
00485 }
00486
00487
00488 base::Board* base::Board::Connect(const char* url, ClientRole role)
00489 {
00490 return base::BoardFactory::CreateBoard(url, role);
00491 }
00492
00493 bool base::Board::Close(Board* brd)
00494 {
00495 return base::BoardFactory::DestroyBoard(brd);
00496 }
00497
00498
00499
00501
00502 uint32_t base::Board::getHardwareVersion()
00503 {
00504 uint32_t val = 0;
00505 get(base::addr_HardwareVersion, val);
00506 return val;
00507 }
00508
00509
00511
00512 uint32_t base::Board::getHardwareType()
00513 {
00514 uint32_t val = 0;
00515 get(base::addr_HardwareType, val);
00516 return val;
00517 }
00518
00519
00520
00522
00523 uint32_t base::Board::initBoard(const char* name, uint32_t minversion)
00524 {
00525 base::OperList lst;
00526 lst.addGet(base::addr_BoardId);
00527 lst.addGet(base::addr_HardwareVersion);
00528 lst.addGet(base::addr_HardwareType);
00529 if (operGen(lst)!=0) return 0;
00530
00531 fBrdNumber = lst.oper(0).value;
00532 uint32_t roc_hw_ver = lst.oper(1).value;
00533 uint32_t roc_typ = lst.oper(2).value;
00534
00535 if(roc_hw_ver < minversion) {
00536 Debug(-1, "The %s you want to access has hardware version %s", name, versionToString(roc_hw_ver));
00537 Debug(-1, "Please update your hardware to version %s", versionToString(minversion));
00538 }
00539
00540 const char* fe_typ = "<unknown>";
00541 switch (roc_typ >> 16) {
00542 case base::kind_nXYTER: fe_typ = "nXYTER"; break;
00543 case base::kind_oldFEET: fe_typ = "FEET 0.1"; break;
00544 case base::kind_FEET: fe_typ = "FEET"; break;
00545 case base::kind_newNX: fe_typ = "nXYTER 2.0"; break;
00546 case base::kind_SPADIC: fe_typ = "SPADIC"; break;
00547 }
00548
00549 const char* be_typ = "<unknown>";
00550 switch (roc_typ & 0xffff) {
00551 case base::kind_Optic: be_typ = "Optic"; break;
00552 case base::kind_FX20: be_typ = "Eth-FX20"; break;
00553 case base::kind_FX40: be_typ = "Eth-FX40"; break;
00554 case base::kind_FX60: be_typ = "Eth-FX60"; break;
00555 case base::kind_newOptic: be_typ = "Optic2"; break;
00556 }
00557
00558 Debug(0, "BRD%u %s HW version: %s; front:%s; back:%s",
00559 fBrdNumber, name, versionToString(roc_hw_ver), fe_typ, be_typ);
00560
00561 return roc_hw_ver;
00562 }
00563
00564
00565
00567
00568 uint32_t base::Board::getBoardNumber()
00569 {
00570 uint32_t num = 0;
00571 if (get(base::addr_BoardId, num)==0)
00572 fBrdNumber = num;
00573 return num;
00574 }
00575
00576
00577
00579
00580 void base::Board::setBoardNumber(uint32_t num)
00581 {
00582 put(base::addr_BoardId, num);
00583 }
00584
00585
00586
00587
00588
00589 base::BoardFactory* base::BoardFactory::gArr[base::BoardFactory::MaxNumFactories] =
00590 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00591
00592
00593
00594 base::BoardFactory::BoardFactory()
00595 {
00596 for (int n=0;n<MaxNumFactories;n++)
00597 if (gArr[n]==0) {
00598 gArr[n] = this;
00599 break;
00600 }
00601 }
00602
00603
00604
00605 base::BoardFactory::~BoardFactory()
00606 {
00607 for (int n=0;n<MaxNumFactories;n++)
00608 if (gArr[n]==this) gArr[n] = 0;
00609 }
00610
00611
00612
00613
00614 base::Board* base::BoardFactory::CreateBoard(const char* url, ClientRole role)
00615 {
00616 if ((url==0) || (strlen(url)==0)) return 0;
00617
00618
00619 for (int n=0;n<MaxNumFactories;n++) {
00620 if (gArr[n]==0) continue;
00621 if (!gArr[n]->IsFactoryFor(url)) continue;
00622
00623 base::Board* brd = gArr[n]->DoConnect(url, role);
00624
00625 if (brd==0) {
00626 fprintf(stderr,"Fail to create board with url %s\n", url);
00627 return 0;
00628 }
00629
00630 brd->fBrdFactory = gArr[n];
00631
00632 return brd;
00633 }
00634
00635 fprintf(stderr,"Cannot create board with url %s - no proper factory found\n", url);
00636
00637 return 0;
00638 }
00639
00640 bool base::BoardFactory::DestroyBoard(base::Board* brd)
00641 {
00642 if (brd==0) return true;
00643
00644 BoardFactory* fact = brd->fBrdFactory;
00645
00646 if (fact==0) return false;
00647
00648 return fact->DoClose(brd);
00649 }
00650
00651
00652 void base::BoardFactory::ShowDebug(int lvl, const char* msg)
00653 {
00654 if (msg!=0) fprintf(lvl<0 ? stderr : stdout, "%s\n", msg);
00655 }