Skip to content
Open
5 changes: 5 additions & 0 deletions config/config_scaler.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0"?>
<scaler address="0xabcd0000" header="true">
<poi>4294967295</poi> <!-- full coverage -->
<data_format>26bit</data_format>
</scaler>
22 changes: 21 additions & 1 deletion include/VMEReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "VME_CFDV812.h"
#include "VME_CAENETControllerV288.h"
#include "VME_TDCV1x90.h"
#include "VME_ScalerV8x0.h"

#include "NIM_HVModuleN470.h"

Expand Down Expand Up @@ -58,6 +59,23 @@ class VMEReader : public Client
inline size_t GetNumTDC() const { return fTDCCollection.size(); }
inline VME::TDCCollection GetTDCCollection() { return fTDCCollection; }

/**
* \brief Add a scaler to handle
* \param[in] address 32-bit address of the scaler module on the VME bus
* Create a new scaler handler for the VME bus
*/
void AddScaler(uint32_t address);
/**
* \brief Get a scaler on the VME bus
* Return a pointer to the scaler object, given its physical address on the VME bus
*/
inline VME::ScalerV8x0* GetScaler(uint32_t address) {
if (fScalerCollection.count(address)==0) return 0;
return fScalerCollection[address];
}
inline size_t GetNumScaler() const { return fScalerCollection.size(); }
inline VME::ScalerCollection GetScalerCollection() { return fScalerCollection; }

void AddIOModule(uint32_t address);
inline VME::IOModuleV262* GetIOModule() { return fSG; }

Expand Down Expand Up @@ -166,8 +184,10 @@ class VMEReader : public Client
VME::CFDCollection fCFDCollection;
/// Pointer to the VME input/output module object
VME::IOModuleV262* fSG;
/// Pointer to the VME general purpose FPGA unit object
/// A set of pointers to VME general purpose FPGA unit objects indexed by their physical VME address
VME::FPGAUnitCollection fFPGACollection;
/// A set of pointers to scaler objects indexed by their physical VME address
VME::ScalerCollection fScalerCollection;
/// Pointer to the VME CAENET controller
VME::CAENETControllerV288* fCAENET;
/// Pointer to the NIM high voltage module (passing through the CAENET controller)
Expand Down
195 changes: 195 additions & 0 deletions include/VME_ScalerV8x0.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
#ifndef VME_ScalerV8x0_h
#define VME_ScalerV8x0_h

#include <vector>
#include <map>
#include <string.h>

#include "VME_GenericBoard.h"

#define TDC_ACQ_STOP 20001

namespace VME
{
/**
* \date 17 Sep 2015
* \author Laurent Forthomme <[email protected]>
*/
enum ScalerV8x0DataFormat { DF32bit=0x0, DF26bit=0x1 };
enum ScalerV8x0TriggerSource { TSExternalTrigger=0x0, TSTimerTrigger=0x1, TSVMETrigger=0x2 };

/**
* \brief Parser for a scaler event/header
* \date 17 Sep 2015
* \author Laurent Forthomme <[email protected]>
*/
class ScalerEvent
{
public:
inline ScalerEvent(unsigned int word) : fWord(word) {;}
inline ~ScalerEvent() {;}

inline unsigned int GetWord() const { return fWord; }

inline unsigned short GetGEO() const { return ((fWord>>27)&0x1f); }
inline bool IsHeader(unsigned short geo=0) const {
bool header_bit = (fWord>>26)&0x1;
if (geo>0) return (header_bit and GetGEO()==geo);
return header_bit;
}

inline unsigned short GetTriggerNumber(unsigned short geo=0) const {
if (!IsHeader(geo)) throw Exception(__PRETTY_FUNCTION__, "Trying to extract the trigger number from a non-header ScalerEvent word", JustWarning);
return (fWord&0xffff);
}
inline ScalerV8x0TriggerSource GetTriggerSource(unsigned short geo=0) const {
if (!IsHeader(geo)) throw Exception(__PRETTY_FUNCTION__, "Trying to extract the trigger source from a non-header ScalerEvent word", JustWarning);
return static_cast<ScalerV8x0TriggerSource>((fWord>>16)&0x3);
}
inline unsigned short GetNumChannels(unsigned short geo=0) const {
if (!IsHeader(geo)) throw Exception(__PRETTY_FUNCTION__, "Trying to extract the number of enabled channels from a non-header ScalerEvent word", JustWarning);
return ((fWord>>18)&0x3f);
}

inline unsigned short GetChannelId() const { return ((fWord>>27)&0x1f); }
inline unsigned int GetChannelCounter(const ScalerV8x0DataFormat& df) const {
switch (df) {
case DF32bit: return fWord;
case DF26bit: return (fWord&0x3ffffff);
}
}

private:
unsigned int fWord;
};

/// A collection of ScalerEvent objects
typedef std::vector<ScalerEvent> ScalerEventCollection;

/**
* \brief List of registers to handle a CAEN V8x0 scaler module
* \date 17 Sep 2015
* \author Laurent Forthomme <[email protected]>
*/
enum ScalerV8x0Register {
kV8x0OutputBuffer = 0x0000,
kV8x0ChannelValue = 0x1000,
kV8x0ChannelEnable = 0x1100,
kV8x0Control = 0x1108,
kV8x0Status = 0x110e,
kV8x0GEO = 0x1110,
kV8x0TriggerCounter = 0x1128,
kV8x0FWVersion = 0x1132,
kV8x0OUI = 0x402a,
kV8x0ModelVersion = 0x4032,
kV8x0HWRevision = 0x404e,
kV8x0SerialMSB = 0x4f02,
kV8x0SerialLSB = 0x4f06
};

/**
* \date 17 Sep 2015
* \author Laurent Forthomme <[email protected]>
*/
class ScalerV8x0Control
{
public:
inline ScalerV8x0Control(unsigned short word): fWord(word) {;}
inline ~ScalerV8x0Control() {;}

inline unsigned short GetWord() const { return fWord; }

enum AcquisitionMode { TriggerDisabled=0x0, TriggerRandom=0x1, PeriodicalTrigger=0x2 };
inline void SetAcquisitionMode(const AcquisitionMode& mode) { SetBit(0, mode&0x1); SetBit(1, (mode>>1)&0x1); }
inline AcquisitionMode GetAcquisitionMode() const {
unsigned short word1 = GetBit(0), word2 = GetBit(1);
return static_cast<AcquisitionMode>(word1+(word2<<1));
}

inline void SetDataFormat(const ScalerV8x0DataFormat& fmt) { SetBit(2, fmt); }
inline ScalerV8x0DataFormat GetDataFormat() const { return static_cast<ScalerV8x0DataFormat>(GetBit(2)); }

inline void SetBusError(bool enable) { SetBit(4, enable); }
inline bool GetBusError() const { return GetBit(4); }

inline void SetHeader(bool enable) { SetBit(5, enable); }
inline bool GetHeader() const { return GetBit(5); }

inline void SetClearMEB(bool enable) { SetBit(6, enable); }
inline bool GetClearMEB() const { return GetBit(6); }

inline void SetAutoReset(bool enable) { SetBit(7, enable); }
inline bool GetAutoReset() const { return GetBit(7); }

private:
inline bool GetBit(unsigned short id) const { return static_cast<bool>((fWord>>id)&0x1); }
inline void SetBit(unsigned short id, unsigned short value=0x1) {
if (value==GetBit(id)) return;
unsigned short sign = (value==0x0) ? -1 : 1; fWord += sign*(0x1<<id);
}
unsigned short fWord;
};

/**
* \date 17 Sep 2015
* \author Laurent Forthomme <[email protected]>
*/
class ScalerV8x0Status
{
public:
inline ScalerV8x0Status(unsigned short word): fWord(word) {;}
inline ~ScalerV8x0Status() {;}

inline bool DataReady() const { return fWord&0x1; }
inline bool AlmostFull() const { return (fWord>>1)&0x1; }
inline bool Full() const { return (fWord>>2)&0x1; }
inline bool GlobalDataReady() const { return (fWord>>3)&0x1; }
inline bool GlobalBusy() const { return (fWord>>4)&0x1; }
inline bool TermOn() const { return (fWord>>5)&0x1; }
inline bool TermOff() const { return (fWord>>6)&0x1; }
inline bool BusError() const { return (fWord>>7)&0x1; }
private:
unsigned short fWord;
};

/**
* \brief Handler object for a CAEN V8x0 scaler module
* \date 17 Sep 2015
* \author Laurent Forthomme <[email protected]>
*/
class ScalerV8x0 : public GenericBoard<ScalerV8x0Register,cvA32_U_DATA>
{
public:
ScalerV8x0(int32_t bhandle, uint32_t baseaddr);
~ScalerV8x0();

unsigned int GetSerialNumber() const;
unsigned short GetModuleVersion() const;
unsigned short GetModuleType() const;
unsigned short GetManufacturerId() const;
//unsigned short GetIdentifier() const;
unsigned short GetGEO() const;

void SetPOI(unsigned int poi) const;
unsigned int GetPOI() const;

unsigned int GetTriggerCounter() const;

unsigned int GetChannelValue(unsigned short channel_id) const;
ScalerEventCollection FetchEvents();

ScalerV8x0Status GetStatus() const;
ScalerV8x0Control GetControl() const;
void SetControl(const ScalerV8x0Control& control) const;

void abort();

private:
unsigned int* fBuffer;
bool gEnd;
};

typedef std::map<unsigned int,VME::ScalerV8x0*> ScalerCollection;
}

#endif
39 changes: 39 additions & 0 deletions src/VMEReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,27 @@ VMEReader::ReadXML(const char* filename)
} catch (Exception& e) { throw e; }
}
}
for (tinyxml2::XMLElement* asca=doc.FirstChildElement("scaler"); asca!=NULL; asca=asca->NextSiblingElement("scaler")) {
if (const char* address=asca->Attribute("address")) {
unsigned long addr = static_cast<unsigned long>(strtol(address, NULL, 0));
if (!addr) throw Exception(__PRETTY_FUNCTION__, "Failed to parse scaler's base address", Fatal);
try {
try { AddScaler(addr); } catch (Exception& e) { if (fOnSocket) Client::Send(e); }
VME::ScalerV8x0* sca = GetScaler(addr);
VME::ScalerV8x0Control control = sca->GetControl();
if (const char* hdr=asca->Attribute("header")) {
if (!strcmp(hdr, "true") or !strcmp(hdr, "True") or !strcmp(hdr, "1")) control.SetHeader(true);
if (!strcmp(hdr, "false") or !strcmp(hdr, "False") or !strcmp(hdr, "0")) control.SetHeader(false);
}
if (tinyxml2::XMLElement* poi=asca->FirstChildElement("poi")) { sca->SetPOI(atoi(poi->GetText())); }
if (tinyxml2::XMLElement* df=asca->FirstChildElement("data_format")) {
if (!strcmp(df->GetText(), "26bit")) control.SetDataFormat(VME::DF26bit);
if (!strcmp(df->GetText(), "32bit")) control.SetDataFormat(VME::DF32bit);
}
sca->SetControl(control);
} catch (Exception& e) { throw e; }
}
}
std::cout << "Global acquisition mode: " << fGlobalAcqMode << std::endl;
unsigned int run = GetRunNumber();
std::ifstream source(filename, std::ios::binary);
Expand Down Expand Up @@ -232,6 +253,24 @@ VMEReader::AddTDC(uint32_t address)
throw Exception(__PRETTY_FUNCTION__, os.str(), Info, TDC_ACQ_START);
}

void
VMEReader::AddScaler(uint32_t address)
{
if (!fBridge) throw Exception(__PRETTY_FUNCTION__, "No bridge detected! Aborting...", Fatal);
try {
fScalerCollection.insert(std::pair<uint32_t,VME::ScalerV8x0*>(
address,
new VME::ScalerV8x0(fBridge->GetHandle(), address)
));
} catch (Exception& e) {
e.Dump();
if (fOnSocket) Client::Send(e);
}
std::ostringstream os;
os << "Scaler with base address 0x" << std::hex << address << " successfully built";
throw Exception(__PRETTY_FUNCTION__, os.str(), Info, TDC_ACQ_START);
}

void
VMEReader::AddCFD(uint32_t address)
{
Expand Down
Loading