#include "base/Board.h" #include #include #include //---------------------------------------------------------------------------- //! Convert role state to a string representation const char* base::roleToString(base::ClientRole role) { switch (role) { case roleNone: return 0; case roleObserver: return "Observer"; case roleControl: return "Control"; case roleDAQ: return "DAQ"; } return 0; } //---------------------------------------------------------------------------- //! Setup the role of the client application base::ClientRole base::defineClientRole(const char* name, base::ClientRole dflt) { if ((name==0) || (strlen(name)==0)) return dflt; if (strcmp(name,"Observer")==0) return roleObserver; if (strcmp(name,"Control")==0) return roleControl; if (strcmp(name,"DAQ")==0) return roleDAQ; return dflt; } base::Board::Board() : fBrdFactory(0), fDefaultTimeout(2.), fVerbosity(0), fOperTrace(1), fRole(roleNone), fBrdNumber(0) { } base::Board::~Board() { } //---------------------------------------------------------------------------- //! Print a formatted debug message. /*! * If the debug level \a lvl is less or equal to the verbosity level * setup with setVerbosity() a message will be printed with ShowDebug(). * The message text is defined by the \c printf style format \a fmt and * variable length argument list. * \param lvl debug level * \param fmt format a la \c printf * \par Example: * \code * Debug(-1, "Error reading Register %d on bus %d", reg, num); * \endcode */ void base::Board::Debug(int lvl, const char *fmt, ...) { if (!fmt || (lvl>getVerbosity())) return; va_list args; va_start(args, fmt); int result(128), length(128); char *buffer = 0; while (result==length) { if (buffer) delete [] buffer; length *= 2; buffer = new char [length + 1]; memset(buffer, 0, length + 1); result = vsnprintf(buffer, length, fmt, args); if (result<0) break; } if (fBrdFactory) fBrdFactory->ShowDebug(lvl, buffer); else fprintf(lvl<0 ? stderr : stdout, "%s\n", buffer); delete [] buffer; va_end(args); } //---------------------------------------------------------------------------- //! Generate output for get/put/operGen traces. /*! * \param isput 'isput' array * \param addr 'addr' array (or pointer to address in case of get/put) * \param value 'value' array (or pointer to value in case of get/put) * \param num request list length * \param rc return code */ void base::Board::traceOper(OperList& lst, int rc) { if (fOperTrace == 0) return; if (fOperTrace == 1 && rc != kOperNetworkErr) return; if (fOperTrace == 2 && rc == 0) return; for (int i=0; i", lst.oper(i).value, lst.oper(i).value, (rc == 0) ? "ok" : "FAIL"); } else { const char* stat = ""; if (i == lst.number()-1) stat = (rc == 0) ? "ok" : "FAIL"; Debug(0, "op[%02d](%u,%08x %-27s) %s 0x%08x %10d %s", i, GetBoardId(), lst.oper(i).addr, aname, (lst.oper(i).isput ? "<-" : "->"), lst.oper(i).value, lst.oper(i).value, stat); } if (rc != 0) { std::string str = operErrToString(rc); Debug(0, " %s", str.c_str()); } } } int base::Board::operGen(bool* isput, uint32_t* addr, uint32_t* value, int num, double tmout) { OperList lst(num, isput, addr, value); int res = operGen(lst, tmout); for (int n=0;n readback verify error | | | | | string representation of error code | error code index part \endverbatim */ std::string base::Board::operErrToString(int rc) { char buf[32]; if (rc <0) { snprintf(buf, sizeof(buf), "rc = %d", rc); return std::string(buf); } snprintf(buf, sizeof(buf), "rc = %4d,%2d -> ", operErrIndex(rc), operErrCode(rc)); std::string str(buf); return str+operErrCodeName(rc); } //---------------------------------------------------------------------------- //! Add an entry to the ROC control space address mapping table. /*! * This method is protected and used in the contructors to initialize * the table. * \sa findRegNameByAddress(), findRegAddressByName(), printRegAddressMap() */ void base::Board::addRegAddrMapping(const char* name, uint32_t addr) { std::string sname(name); fMapName2Addr[sname] = addr; fMapAddr2Name[addr] = sname; } //---------------------------------------------------------------------------- //! Retrieve a ROC control space address by its symbolic name. /*! * Locates in the ROC control space address mapping table the entry for * the name \a name and returns the associated address in \a addr. * \param name name to be looked up * \param addr address to be returned * \returns found address value or kAddrError if address not found * \sa findRegNameByAddress(), addRegAddrMapping(), printRegAddressMap() */ uint32_t base::Board::findRegAddressByName(const char* name) { mapn2a_t::iterator it = fMapName2Addr.find(std::string(name)); if (it != fMapName2Addr.end()) return it->second; return kAddrError; } //---------------------------------------------------------------------------- //! Retrieve symbolic name of a ROC control space address. /*! * Locates in the Board control space address mapping table the entry for * the address \a addr and returns the associated symbolic name in \a name. * \param addr address to be looked up * \returns symbolic name of the register, 0 when not found * \sa findRegAddressByName(), addRegAddrMapping(), printRegAddressMap() */ const char* base::Board::findRegNameByAddress(uint32_t addr) { if (addr==kAddrError) return 0; mapa2n_t::iterator it = fMapAddr2Name.find(addr); if (it != fMapAddr2Name.end()) return it->second.c_str(); // ok because entries never deleted return 0; } //---------------------------------------------------------------------------- void base::Board::printRegAddressMap(std::ostream& os, bool byname) { char sbuf[1000]; if (byname) { for (mapn2a_t::iterator it=fMapName2Addr.begin(); it!=fMapName2Addr.end(); it++) { snprintf(sbuf, sizeof(sbuf), "0x08x : %s", (unsigned) it->second, (const char*) (it->first.c_str())); os << sbuf << std::endl; } } else { for (mapa2n_t::iterator it=fMapAddr2Name.begin(); it!=fMapAddr2Name.end(); it++) { snprintf(sbuf, sizeof(sbuf), "0x08x : %s", (unsigned) it->first, (const char*) (it->second.c_str())); os << sbuf << std::endl; } } } //---------------------------------------------------------------------------- void base::Board::fillRegAddrNames(std::list& lst) { for (mapn2a_t::iterator it=fMapName2Addr.begin(); it!=fMapName2Addr.end(); it++) lst.push_back(it->first); } //---------------------------------------------------------------------------- //! Returns a string representation of a version number const char* base::Board::versionToString(uint32_t ver) { static char sbuf[100]; snprintf(sbuf, sizeof(sbuf), "%u.%u.%u.%u", (ver >> 24), (ver >> 16) & 0xff, (ver >> 8) & 0xff, ver & 0xff); return sbuf; } base::Board* base::Board::Connect(const char* url, ClientRole role) { return base::BoardFactory::CreateBoard(url, role); } bool base::Board::Close(Board* brd) { return base::BoardFactory::DestroyBoard(brd); } //---------------------------------------------------------------------------- //! Returns hardware version of ROC (FPGA firmware version) uint32_t base::Board::getHardwareVersion() { uint32_t val = 0; get(base::addr_HardwareVersion, val); return val; } //---------------------------------------------------------------------------- //! Returns hardware type (frontend/backend) of ROC (FPGA firmware kind) uint32_t base::Board::getHardwareType() { uint32_t val = 0; get(base::addr_HardwareType, val); return val; } //---------------------------------------------------------------------------- //! Checks and print board kind, version and id uint32_t base::Board::initBoard(const char* name, uint32_t minversion) { base::OperList lst; lst.addGet(base::addr_BoardId); lst.addGet(base::addr_HardwareVersion); lst.addGet(base::addr_HardwareType); if (operGen(lst)!=0) return 0; fBrdNumber = lst.oper(0).value; uint32_t roc_hw_ver = lst.oper(1).value; uint32_t roc_typ = lst.oper(2).value; if(roc_hw_ver < minversion) { Debug(-1, "The %s you want to access has hardware version %s", name, versionToString(roc_hw_ver)); Debug(-1, "Please update your hardware to version %s", versionToString(minversion)); } const char* fe_typ = ""; switch (roc_typ >> 16) { case base::kind_nXYTER: fe_typ = "nXYTER"; break; case base::kind_oldFEET: fe_typ = "FEET 0.1"; break; case base::kind_FEET: fe_typ = "FEET"; break; case base::kind_newNX: fe_typ = "nXYTER 2.0"; break; case base::kind_SPADIC: fe_typ = "SPADIC"; break; } const char* be_typ = ""; switch (roc_typ & 0xffff) { case base::kind_Optic: be_typ = "Optic"; break; case base::kind_FX20: be_typ = "Eth-FX20"; break; case base::kind_FX40: be_typ = "Eth-FX40"; break; case base::kind_FX60: be_typ = "Eth-FX60"; break; case base::kind_newOptic: be_typ = "Optic2"; break; } Debug(0, "BRD%u %s HW version: %s; front:%s; back:%s", fBrdNumber, name, versionToString(roc_hw_ver), fe_typ, be_typ); return roc_hw_ver; } //---------------------------------------------------------------------------- //! Returns board number as stored in ROC uint32_t base::Board::getBoardNumber() { uint32_t num = 0; if (get(base::addr_BoardId, num)==0) fBrdNumber = num; return num; } //---------------------------------------------------------------------------- //! Updates board number in device memory void base::Board::setBoardNumber(uint32_t num) { put(base::addr_BoardId, num); } // ============================================================================= base::BoardFactory* base::BoardFactory::gArr[base::BoardFactory::MaxNumFactories] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; //---------------------------------------------------------------------------- base::BoardFactory::BoardFactory() { for (int n=0;nIsFactoryFor(url)) continue; base::Board* brd = gArr[n]->DoConnect(url, role); if (brd==0) { fprintf(stderr,"Fail to create board with url %s\n", url); return 0; } brd->fBrdFactory = gArr[n]; return brd; } fprintf(stderr,"Cannot create board with url %s - no proper factory found\n", url); return 0; } bool base::BoardFactory::DestroyBoard(base::Board* brd) { if (brd==0) return true; BoardFactory* fact = brd->fBrdFactory; if (fact==0) return false; return fact->DoClose(brd); } void base::BoardFactory::ShowDebug(int lvl, const char* msg) { if (msg!=0) fprintf(lvl<0 ? stderr : stdout, "%s\n", msg); }