#include #include #include #include #include #include "base/Url.h" #include "roc/Board.h" #include "roc/defines_roc.h" #include "roc/defines_optic.h" #include "roc/defines_udp.h" #include "feet/defines_feet.h" const char* roc::xmlRocPool = "RocPool"; const char* roc::xmlTransportWindow = "TransportWindow"; const char* roc::xmlTransportKind = "TransportKind"; const char* roc::xmlBoardAddr = "BoardAddr"; const char* roc::xmlRole = "Role"; const char* roc::xmlRocNumber = "RocNumber"; const char* roc::xmlLowWater = "LowWater"; const char* roc::xmlHighWater = "HighWater"; const char* roc::xmlMsgFormat = "MsgFormat"; const char* roc::xmlFlushTime = "FlushTime"; const char* roc::typeUdpDevice = "roc::UdpDevice"; const char* roc::typeAbbDevice = "roc::AbbDevice"; /*! * \page roc_board_opererr roc::Board get/put/oper return codes * * The methods accessing the ROC control space, like * \li get, put, and oper... in roc::Board * \li many set and get methods in classes derived from base::Peripheral * * return an \c int return code. It holds 0 in case the operation succeeded * and is non-zero when it failed. In case of failure * \li the lower 8 bits contain an error code as defined in * roc::Board::operErr and is detailed below * \li the upper 24 bits contain an index or step number. This allows to * reconstruct the point of failure for list or array operations like * roc::Board::operGen. * * Use the methods * \li roc::Board::operErrCode() to retrieve the error code * \li roc::Board::operErrIndex() to retrieve the index value * \li roc::Board::operErrBuild() to build a return code * \li roc::Board::operErrBuildInc() to modify index part of a return code * * The error codes are * \li \e kOperSuccess: success * \li \e kOperAddrErr: invalid address, there is no ROC resource under this * address. * \li \e kOperValueErr: invalid value, the value to be written is not allowed * in the current state of the ROC or ROC peripheral. * Only returned for write type operations. * \li \e kOperStateErr: invalid state, the operation is not allowed in the * current state of the ROC or ROC peripheral. * \li \e kOperNetworkErr: network communication error. * \li \e kOperVerifyErr: verify mismatch, a readback after a write operations * yielded a value different from the written one. * Only returned by dedicated write type operations, * the method name often ends in ...Verify. * \li \e kOperBusErr: secondary bus error. This is returned when a field bus * operation, like on a I2C bus, failed. */ /*! * \class roc::Board * \brief This class represents a single ROC. * * \todo add class docu */ //---------------------------------------------------------------------------- roc::Board::Board() : base::Board() { // current ROC address def's from defines.h addRegAddrMapping("ROC_TYPE", ROC_TYPE); addRegAddrMapping("ROC_HWV", ROC_HWV); addRegAddrMapping("ROC_ROCID", ROC_ROCID); addRegAddrMapping("ROC_ADDSYSMSG", ROC_ADDSYSMSG); addRegAddrMapping("ROC_SYSTEM_RESET", ROC_SYSTEM_RESET); } //---------------------------------------------------------------------------- roc::Board::~Board() { } //---------------------------------------------------------------------------- //! Returns the FPGA type the firmeware was syntesized for uint32_t roc::Board::getRocFpgaType() { uint32_t num = 0; get(ROC_FPGA_TYPE, num); return num; } //---------------------------------------------------------------------------- //! Returns subversion revision number of the ROC firmware source code uint32_t roc::Board::getRocSvnRev() { uint32_t num = 0; get(ROC_SVN_REVISION, num); return num; } //---------------------------------------------------------------------------- //! Returns the time the firmware was synthesized. /*! * The time is given in numbers of seconds since 1970-01-01 0:00 . */ uint32_t roc::Board::getRocBuildTime() { uint32_t num = 0; get(ROC_BUILD_TIME, num); return num; } //---------------------------------------------------------------------------- //! Add an commands list entry . /*! * This method sets commands list, which can be executed by * command activateCommandsList() or by issuing of DLM */ int roc::Board::uploadCommandsList(unsigned num, const base::OperList& lst, double tmout) { if (num >= ROC_CMD_LST_NUMBER) { Debug(-1, "Wrong number %u of commands list", num); return ROC_ADDRESS_ERROR; } base::OperList setlst; unsigned addr = ROC_CMD_LST_MEM + num * ROC_CMD_LST_SIZE / ROC_CMD_LST_NUMBER; for (int n=0;n= ROC_CMD_LST_MEM + ROC_CMD_LST_SIZE) { Debug(-1, "Commands list to long %d for slot %u", lst.number(), num); return ROC_VALUE_ERROR; } setlst.addPut(addr, ROC_CMD_LST_PUT | (lst.oper(n).addr & ROC_CMD_LST_ADDRMASK)); addr+=4; setlst.addPut(addr, lst.oper(n).value); addr+=4; } // check if last list command not specified, add it if ((lst.number()>0) && (lst.oper(lst.number()-1).addr != ROC_CMD_LST_ACTIVE)) { if (addr >= ROC_CMD_LST_MEM + ROC_CMD_LST_SIZE) { Debug(-1, "Commands list to long %d for slot %u", lst.number(), num); return ROC_VALUE_ERROR; } setlst.addPut(addr, ROC_CMD_LST_PUT | ROC_CMD_LST_ACTIVE); addr+=4; setlst.addPut(addr, 0); addr+=4; } return operGen(setlst, tmout); } //---------------------------------------------------------------------------- //! Download commands list from the ROC. /*! * Method reads specified commands list from the board. */ int roc::Board::downloadCommandsList(unsigned num, base::OperList& lst, double tmout) { lst.clear(); if (num >= ROC_CMD_LST_NUMBER) { Debug(-1, "Wrong number %u of commands list", num); return ROC_ADDRESS_ERROR; } base::OperList getlst; unsigned addr = ROC_CMD_LST_MEM + num * ROC_CMD_LST_SIZE / ROC_CMD_LST_NUMBER; unsigned lastaddr = addr + ROC_CMD_LST_SIZE / ROC_CMD_LST_NUMBER; while (addr (brd); if (rocbrd==0) { fprintf(stderr,"Non-ROC board created with url %s\n", name); base::Board::Close(brd); return 0; } return rocbrd; } //---------------------------------------------------------------------------- bool roc::Board::Close(Board* brd) { return base::Board::Close(brd); } //---------------------------------------------------------------------------- //! Returns software version of client software uint32_t roc::Board::getRoclibVersion() { return KNUT_VERSION; } //---------------------------------------------------------------------------- //! Returns hardware version of ROC (FPGA firmware version) uint32_t roc::Board::getRocHardwareVersion() { uint32_t val = 0; get(ROC_HWV, val); return val; } //---------------------------------------------------------------------------- //! Returns hardware type (frontend/backend) of ROC (FPGA firmware kind) /** * Frontend: * 1 - NX * 2 - FEET * Backend: * 1 - Optics * 2 - Ethernet FX20 * 3 - Ethernet FX40 */ uint32_t roc::Board::getRocHardwareType() { uint32_t val = 0; get(ROC_TYPE, val); return val; } //---------------------------------------------------------------------------- //! Clears the FIFO in ROC (discard all old data) void roc::Board::clearRocFifo() { operPP(ROC_NX_FIFO_RESET, 1, ROC_NX_FIFO_RESET, 0); } //---------------------------------------------------------------------------- //! Full ROC restart (FPGA and PPC, if used) /*! * This methods sends a message to the ROC which causes a full reset * of the ROC board, the FPGA is reconfigured, and if used, the PPC is * rebooted. Due to this hard reset the connection between the Board object * and the ROC will abort, the Board object will essentially be a zombie * after restartRoc() is called. * * This method can come in handy when the ROC is in an inaccessible place * and partially hung. * * \post ROC restarting, Board object defunct. */ void roc::Board::restartRoc() { put(ROC_SYSTEM_RESET, 1); } //---------------------------------------------------------------------------- //! Returns the status of the throttle system. /*! * \param val bit mask with throttle system state * \li bit 0 set indicates that throttling is active, thus data is currently * been discarded. * \li bit 1 set indicates that the throttle request flip-flop is set and that * a throttle request is emitted from GPIO pin 0. * * \returns see \ref roc_board_opererr */ int roc::Board::getRocThrottleState(uint32_t& val) { return get(ROC_NX_THROTTLE, val); } //! Check if specified address is address of the board, connected via UDP /*! * First checks that it has udp protocol * If not, than check if it is not starts with abb * File should be checked before */ bool roc::Board::IsUdpAddress(const char* name) { base::Url url(name); // for any kind of invalid url we will try to create udp if (!url.IsValid()) return true; if (url.GetProtocol()=="udp") return true; if (url.GetProtocol().empty() && (url.GetHostName().find("abb")!=0)) return true; return false; } //! Check if specified address is address of board, connected via optic /*! * First checks that it has prefix optic://, second that name starts from abb */ bool roc::Board::IsOpticAddress(const char* name) { base::Url url(name); if ((url.GetProtocol().length()>0) && (url.GetProtocol()!="optic")) return false; // any optic address must contain abb in the beginning of the address return url.GetHostName().find("abb")==0; } //! Check if specified address is lmd filename /*! * First checks that it has protocol file:// or has .lmd extension */ bool roc::Board::IsLmdFileAddress(const char* name) { base::Url url(name); if (!url.IsValid()) return false; if (url.GetProtocol()=="file") return true; if (url.GetProtocol().empty() && (url.GetFullName().find(".lmd")!=std::string::npos)) return true; return false; }