/* * jlabSSPDIRCBoard.hh * * Created on: January 8, 2019 * Author: * * This class provides interface that EPICS support will use to monitor * and control the JLAB SSPD boards for DIRC. * All methods, including accesssors, need to be thread-safe since they * may be executing simultaneously on multiple threads. */ #ifndef _jlabSSPDIRCBoard_HH_ #define _jlabSSPDIRCBoard_HH_ #include #include #include #include #include #include #include "jlabBoard.hh" #include "jlabROCSharedMemoryWrapper.hh" using namespace std; class jlabSSPDIRCBoard: public jlabBoard { public: // Constructor. Create SSPDIRC board object specified by base address // Create all channel objects on that board and fill the channel vector. // Throws an exception if fails to create the object. jlabSSPDIRCBoard( uint32_t locSlotNumber, jlabROCSharedMemoryWrapper* locROCSharedMemoryWrapper ); // Destructor. Destroys this board. virtual ~jlabSSPDIRCBoard(); // Return boards type SSPDIRC_v2 or whatever virtual string GetType(); // Return the 32-bit status word for this board virtual uint32_t GetStatus(); // Return the number of channels this board is serving static uint32_t GetNumberOfChannels(); static uint32_t GetNumberOfFibers(); // Start reading the scaler data for this board from VME bus virtual void StartScalers( const string scalerType = "" ); // Stop reading the scaler data for this board from VME bus virtual void StopScalers( const string scalerType = "" ); // Return scaler values for particular channel for this board, in Hz or raw // Time is in seconds // Scalar Type: Readout1, Readout2, Trigger1, Trigger2 virtual vector GetScalers( uint32_t locChannel, string locScalarType, vector& locTimes, bool locOutputInHzFlag = true ); virtual double GetScaler( uint32_t locChannel, string locScalarType, bool locOutputInHzFlag = true ); // Return clock counts for this board virtual vector GetClockCounts( void ); // Get a vector of thresholds for a particular type of thresholds virtual vector GetThresholds( const string threshType ); // Get the values of threshold for a single channel of a particular threshold type virtual double GetThreshold( const unsigned chanNumb, const string threshType ); // Set thresholds for particular type of thresholds for all channels virtual void SetThresholds( const double threshold, const string threshType = "" ); // Set thresholds for particular type of threshold for a single channel virtual void SetThreshold( uint32_t locChannelNumber, const double threshold, const string threshType ); // Return the histogram for energy spectrum for a particular channel vector GetSpectrum( const unsigned chanNumb ); // Return the most recent temperature reading for the channel double GetTemperature( uint32_t locChannel, uint32_t dataType ); bool isFiberConneced( uint32_t fiber ); void Set_Data( vmeDIRC_Scalers locInputScalers ); void GetFiberValues( vmeDIRC_Scalers locInputScalers ); std::vector< vector< double > >& GetTempAndVoltArray() { return dTempAndVoltArray; } // Try to update a lot slower virtual double GetUpdateTime() { return 1.0; } static std::vector& GetTempNames() { return dTempNames; } // Translate the channel number that comes from the SSP board readout into the channel number // that is stored in the translation table and that is used as the EPICS asyn parameter channel number. // Got this formula from Justin Stevens. static unsigned GetEPICSChannelNumber( unsigned fiberNumber, unsigned fpgaChannel ) { return (fiberNumber << 8) + fpgaChannel; } // Translate the channel number from the translation table into the fiber number from the SSP board. // The formula is the inversion for fiber number of the formula from Justin Stevens. static unsigned GetFiberNumber( unsigned epicsChannelNumber ) { return (epicsChannelNumber>>8); } bool IsFiberConnected( uint32_t fiber ); epicsAlarmCondition GetAlarmStatus( uint32_t fiber ); epicsAlarmSeverity GetAlarmSeverity( uint32_t fiber ); bool IsUpdateRunning(); bool SetUpdateIsRunning( bool stat = true ); protected: // Prevent copying boards jlabSSPDIRCBoard( const jlabSSPDIRCBoard& board ); jlabSSPDIRCBoard& operator=( const jlabSSPDIRCBoard& board ); // Total number of DIRC PMT channels served by a single SSP board 192x24=4608 in decimal. // DIRC SSP use only 24 channels per board. To bunch all channels together D. Lawrence // ended up having a range of channels from 0 to 6079, some of the are non-real. // static const unsigned dNumChannels = 6080 ; // Number of channels that are served by a single channel of SSP static const unsigned dNumberChannelsPerFiber = DIRC_MAX_SCALER_FIBER; static const unsigned dNumberFibers = DIRC_MAX_FIBER; static const unsigned dNumChannels = dNumberFibers * dNumberChannelsPerFiber; // Conversion constant for voltages and temperatures static const double dTempConversionConstant = 1000.0 ; // Define the names of the temperature types coming from the FPGA. the order is important // since the data coming from SSP is pre-sorted assuming the order below. // Also these names are supposed to be used in the EPICS DB in the input fields. static std::vector dTempNames; // Only access the below within a lock! // Time is in seconds, and frequency is in Hz // vector: For when data is collected over a period of time (each index one point in time) vector dScalarCountTimer_Readout1; vector dScalarRateTimer_Readout1; vector dTemperatureTimer; // The first key is a string indicating the temperature type, the second unsigned integer is indicating the fiber number // std::map > > dTempAndVoltArray; // The first index is the temperature type, the second is the fiber number. std::vector< std::vector< double > > dTempAndVoltArray; // Number of reading cycles that the given fiber did not get read because it was missing // in the data from the shared memory. std::vector dFiberTimoutCounter ; // Number of reading attempts without data for a given fiber before the timout is declared // and an alarm is raised for that missing fiber. static const unsigned dMaxReadingForTimout = 10; bool dUpdateIsRunning; // The unsigned keys are the channel number map > dScalarCountMap_Readout1; map > dScalarRateMap_Readout1; }; // DEFINE ME inline jlabSSPDIRCBoard::jlabSSPDIRCBoard( uint32_t locSlotNumber, jlabROCSharedMemoryWrapper* locROCSharedMemoryWrapper ) : jlabBoard( locSlotNumber, locROCSharedMemoryWrapper ), dScalarCountTimer_Readout1(), dScalarRateTimer_Readout1(), dTemperatureTimer(), dTempAndVoltArray( DIRC_MAX_DATA_FIBER, vector( dNumberChannelsPerFiber, -9999.0 ) ), dFiberTimoutCounter( dNumberFibers, 0 ), dUpdateIsRunning( true ), dScalarCountMap_Readout1(), dScalarRateMap_Readout1() { return; } // DEFINE ME inline jlabSSPDIRCBoard::~jlabSSPDIRCBoard( void ) { } inline string jlabSSPDIRCBoard::GetType() { return "SSPDIRC"; } // DEFINE ME inline uint32_t jlabSSPDIRCBoard::GetStatus() { return 0; } // Number of Channel for EPICS asyn driver inline uint32_t jlabSSPDIRCBoard::GetNumberOfChannels() { // The number of "channels" for EPICS parameters is different from the number of // actual of channels for this boards because D. Lawrence introduced gaps. return GetEPICSChannelNumber( (dNumberFibers - 1), dNumberChannelsPerFiber ); } // Return number of fibers in SSP board inline uint32_t jlabSSPDIRCBoard::GetNumberOfFibers() { return dNumberFibers; } inline void jlabSSPDIRCBoard::StartScalers( const string scalerType ) { // DEFINE ME return; } inline void jlabSSPDIRCBoard::StopScalers( const string scalerType ) { // DEFINE ME return; } // DEFINE ME inline vector jlabSSPDIRCBoard::GetClockCounts( void ) { return vector(); } // DEFINE ME inline void jlabSSPDIRCBoard::SetThresholds( const double threshold, const string threshType ) { return; } // DEFINE ME inline void jlabSSPDIRCBoard::SetThreshold( const unsigned chanNumber, const double threshold, const string threshType ) { return; } // DEFINE ME inline vector jlabSSPDIRCBoard::GetThresholds( const string threshType ) { return vector(); } // DEFINE ME inline double jlabSSPDIRCBoard::GetThreshold( const unsigned chanNumb, const string threshType ) { return 0.0; } // DEFINE ME inline vector jlabSSPDIRCBoard::GetSpectrum( const unsigned chanNumb ) { return vector(); } inline bool jlabSSPDIRCBoard::IsFiberConnected( uint32_t fiber ) { if( 0 <= fiber && fiber < dFiberTimoutCounter.size() && dFiberTimoutCounter[fiber] <= dMaxReadingForTimout ) { return true; } else { return false; } } inline epicsAlarmCondition jlabSSPDIRCBoard::GetAlarmStatus( uint32_t fiber ) { if( IsFiberConnected(fiber) && dUpdateIsRunning ) return epicsAlarmNone; else return epicsAlarmRead; } inline epicsAlarmSeverity jlabSSPDIRCBoard::GetAlarmSeverity( uint32_t fiber ) { if( IsFiberConnected(fiber) && dUpdateIsRunning ) return epicsSevNone; else return epicsSevInvalid; } inline bool jlabSSPDIRCBoard::IsUpdateRunning() { return dUpdateIsRunning; } inline bool jlabSSPDIRCBoard::SetUpdateIsRunning( bool stat ) { return (dUpdateIsRunning = stat); } #endif /* _jlabSSPDIRCBoard_HH_ */