#ifndef _mdet_FrontEnd_h #define _mdet_FrontEnd_h #include #include #include #include // just forward it, to declare friendship. #include #include // allow the use of ULong64_t namespace det { struct ComponentUpdater; // Actually not needed because PMT.h -> MComponentGroup.h -> ComponentGroup.h } namespace mdet { class Module; /** * \class FrontEnd FrontEnd.h "mdet/FrontEnd.h" * * \brief Electronic front-end for the modules. * * Multi-channel electronic device meant to register * the signal that came out from each PMT pixel. * * \author Rodolfo Federico Gamarra * \date 24 Mar 2009 * \ingroup mdet */ class FrontEnd : public MDetectorComponent::Type { private: /** * \brief Type for the set of associated mdet::Channel. */ typedef MComponentGroup::Type ChannelGroup; public: /** * \brief Encapsulates the sampling logic. * * This auxiliary object encapsulates the logic * neccesary to simulate the sampling proccess of * the FPGA. * * \sa MakeSampler */ class Sampler { public: /** * \brief Digitally sample the voltage. * * Note that this method isn't const due to * that we take into account the (possible) * effects of the sampling proccess on itself. */ bool operator()(double v); private: /// Allow construction. friend class FrontEnd; /// Construct with the associated FrontEnd. Sampler(const FrontEnd& fe); /// By now the criteria is to depend only in the last sample. bool fLastSample; const FrontEnd& fFrontEnd; }; static const char* const kComponentName; static const char* const kComponentId; typedef std::vector BrokenChannelContainer; /** * \brief Convenience typedef for const iterator over * the contained mdet::Channel instances. */ typedef ChannelGroup::ConstIterator ChannelConstIterator; /** * \brief Begin iterator over the contained channels. */ ChannelConstIterator ChannelsBegin() const { return fChannels.Begin(); } /** * \brief End iterator over the contained channels. */ ChannelConstIterator ChannelsEnd() const { return fChannels.End(); } /** * \brief Mean electronic sample rate period. * * This is the (mean) time elapsed between * consecutive digital samples. * Tipically in the order of ns. * * \sa MakeSampler */ double GetMeanSampleRatePeriod() const; /** * \brief Electronic's jitter in sample rate. * * It's a relative factor over the mean value. * * From this value several different quantities could be derived: * (i) the standard deviation of a Gaussian jitter distribution. * (ii) the upper and lower limits of a Uniform jitter distribution. * * \sa MakeSampler */ double GetSampleRatePeriodJitter() const; /** * \brief Number of bins of the (cyclic) pre-T1 buffer. * @sa GetExternalMemoryBufferLength() */ unsigned int GetPreT1BufferLength() const; /** * \brief Number of bins of the post-T1 buffer. * @sa GetExternalMemoryBufferLength() */ unsigned int GetPostT1BufferLength() const; /** * \brief Number of bins of the buffer. * @sa GetBufferLength() */ unsigned int GetBufferLength() const { return GetPreT1BufferLength()+GetPostT1BufferLength(); } /** * \brief Size of the (cyclic) external memory buffer * associated to each module. * @sa GetPreT1BufferLength * @sa GetPostT1BufferLength * * The working strategy is signal collecting is goes like this. * On a loop the signal is collected on the PreT1-buffer; when * a significant signal is detected in the tank, a T1 signal * is sent to the front end from the tank. Then the PreT1-buffer * is frozen and the data collection proceeds to write on the * PostT1-buffer. Upon reaching the end of this second stage * buffer, the complete trace (pre+post) is stored in an * external cyclic memory buffer, with room for n complete * (pre+post) buffers (where n is the return value of this * method). For typical values, this length (of the external * memory) amounts to 10 seconds of data acquisition, taking * into account the typical T1 rate from the tanks. * On the other side, upon detection of a T3 configuration CDAS * will ask the Counter / Modules for the traces collected at * (within a tolerance) the T3 time. The external memory buffer * will be scanned and those detected will be sent to CDAS. * As a last remark, note that the tank promotes certain T1 times * to T2, whereas the front end stores only T1 and does no filtering * according to T2 promotion (the actual device was built without a * mechanism to retrieve T2 promotion information from the tank to * the front end). What CDAS promotes to T3 are only what was formerly * promoted to T2, so in this external memory buffer certain (pre+post) * buffers will be stored (temporarily, recall the cyclic nature) * but CDAS will never request them. */ // unsigned int GetExternalMemoryBufferLength() const; /** * \brief Get mask of broken channels. * @sa GetMask() */ ULong64_t GetMask() const; /** * \brief List of broken channels. * @sa GetBrokenChannels() */ const BrokenChannelContainer& GetBrokenChannels() const; /** * \brief The module to which this FrontEnd belongs. */ const Module& GetModule() const; /** * \brief Create a new sampler object. */ Sampler MakeSampler() const; private: /// Forward to channels and to base-class. void Update(bool invalidateData, bool invalidateComponents); /** * \brief Low end-point of the range where the voltage * is taken as a true-value by the FPGA sampling proccess. * * To be a true-value a voltage needs to be higher * than this value. * * \sa Sample * \sa FPGASample */ double GetTrueRangeLowThreshold() const; /** * \brief Hi end-point of the range where the voltage * is taken as a false-value by the FPGA sampling * process. * * To be a false-value a voltage needs to be lower * than this value. * * \sa Sample * \sa FPGASample */ double GetFalseRangeHiThreshold() const; /** * \brief Constructs the electronic front-end. * * \param fId The identifier to be used. * \param parentMap The identifiers of the parent within the hierarchy. * \param parent The parent mdet::Module. * * A reference to the parent is kept in this class. * * This method is kept private; creation of these objects is not * meant to be performed by client code. See the related friendship * declaration. * * \sa mdet::MDectectorComponent::Type */ FrontEnd(int fId, const det::VManager::IndexMap& parentMap, const Module& parent); /** * \brief Destructor (!). */ ~FrontEnd() { } /** * \brief Retrieves the group of channels. */ const ChannelGroup& GetChannels() const { return fChannels; } /** * \brief Friendship to allow construction. Also access to channels (GetChannels). */ friend class Module; /** * \brief Frienship to allow destruction. * * This comes from the fact that the FrontEnd is * kept (in mdet::Module) within one of these. */ friend class utl::ShadowPtr; /// See mdet::Counter. template friend class det::ComponentGroup; ChannelGroup fChannels; /* * Sample rate stuff: Jitter handling. */ mutable utl::Validated fMeanSampleRatePeriod; mutable utl::Validated fSampleRatePeriodJitter; /* * Note that managers do not provide unsigned retrievers. * So use internally a signed one, and do a cast at the * accesor: the interface is kept unsigned as I think * that should be (this is the number of bins, no sense to * be negative). */ mutable utl::Validated fPreT1BufferLength; // See fPreT1BufferLength. mutable utl::Validated fPostT1BufferLength; // See fPreT1BufferLength. mutable utl::Validated fExternalMemoryBufferLength; mutable utl::Validated fTrueRangeLowThreshold; mutable utl::Validated fFalseRangeHiThreshold; mutable utl::ShadowPtr fBrokenChannels; const Module& fModule; }; } #endif // _mdet_FrontEnd_h