FSUDAQ/DigitizerClass.h
2022-08-03 19:00:41 -04:00

856 lines
38 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef DIGITIZER_H
#define DIGITIZER_H
#include <stdio.h>
#include <string>
#include <sstream>
#include <cmath>
#include <cstring> ///memset
#include <iostream> ///cout
#include <bitset>
//#include <TQObject.h>
//#include <RQ_OBJECT.h>
#include "CAENDigitizer.h"
#include "CAENDigitizerType.h"
#include "RegisterAddress.h"
#define MaxNChannels 16
#define MaxRecordLength 0x1fff /// 8191
using namespace std;
struct DigitizerChannelSetting {
/// combined all DPP, PHA, and PSD
unsigned int recordLength; /// ch
unsigned int EventAggr; /// number of events in one aggregate (0=automatic), number of event acculated for read-off
unsigned int dynamicRange; /// 0 = 2 Vpp, 1 = 0.5 Vpp
unsigned int preTrigger; /// the number of samples before the trigger in the waveform saved into memory
float DCOffsetPrecentage; /// precentage of Max ADC
uint32_t VetoWidth; /// see manual, uint32_t to ensure it is 32 bit
bool triggerPolarity; /// 0 = on rising edge, 1 = on falling edge
uint32_t DPPAlgorithmControl;
unsigned int baselineSampling;
unsigned int peakSampling;
bool pulsePolarity_DPP; /// 0 = positive, 1 = negative
bool rollOverFlag;
bool pileUpFlag;
uint32_t DPPAlgorithmControl2;
unsigned int triggerThreshold; /// [LSB]
unsigned int triggerHoldOff; /// [ch], Other triggers are inhibited for the overall Trigger HoldOff duration.
unsigned int shapedTriggerWidth;
/// PHA
unsigned int triggerSmoothingFactor; /// 0x0 = disabled; 0x1 = 2 sample; 0x2 = 4 samples; 0x4 = 8 samples; 0x8 = 16 samples; 0x10 = 32 samples; 0x20 = 64 samples; 0x3F = 128 samples
unsigned int inputRiseTime; /// [ch]
unsigned int trapRiseTime; /// [ch]
unsigned int trapFlatTop; /// [ch]
unsigned int decayTime; /// [ch]
unsigned int peakingTime; /// [ch] flatTop delay, where the samples are used for the calculation of the peak height
unsigned int peakHoldOff; /// [ch] how close must be two trapezoids to be considered piledup after the start of flat top
unsigned int fineGain;
unsigned int riseTimeValidWindow; /// [ch] used by the rise time discriminator (RTD) to reject pulses that overlap in the rise time
/// PDS
unsigned int cfdSetting;
unsigned int chargeZeroSuppThreshold;
unsigned int shortGateWidth;
unsigned int longGateWidth;
unsigned int gateOffset;
unsigned int fixedBaseline;
unsigned int triggerLatency;
unsigned int thresholdPSDCut;
unsigned int pureGapThreshold;
unsigned int earlyBaselineFreeze;
};
//################################################################
class Digitizer{
public:
Digitizer();
Digitizer(int boardID, int portID = 0);
~Digitizer();
void Reset();
int OpenDigitizer(int boardID, int portID = 0);/// portID is for optical link for using PCIe card, from 0, 1, 2, 3
int CloseDigitizer();
///=================Settings
void WriteRegister(uint32_t address, uint32_t value, int ch = -1);
uint32_t ReadRegister(uint32_t address, unsigned int ch);
///common for PHA and PSD digitizers
void SetChannelMask(uint32_t mask);
void SetRecordLength(unsigned int lenght, int ch = -1); /// when ch == -1, mean set all channels
void SetEventAggregation(unsigned int numEvent, int ch = -1);
void SetInputDynamicRange(unsigned int TwoVol_0_or_halfVol_1, int ch = -1);
void SetNumSamplePreTrigger(unsigned int nSample, int ch = -1 );
void SetDCOffset(float offsetPrecentage, int ch = -1);
void SetVetoWidth(uint32_t bit, int ch = -1); /// See manual
void SetTriggerPolarity(bool RiseingIsZero, int ch = -1);
void SetDPPAlgorithmControl(uint32_t bit, bool useControl2 = false, int ch = -1);
void SetDPPAlgorithmControlBit(unsigned int bitValue, unsigned int bitLength, unsigned int bitSmallestPos, bool useControl2 = false, int ch = -1);
void SetTrapezoidRescaling(unsigned int rightShiftBits, int ch = -1); /// DPPAlgoritmControl bit-0:5
void SetPeakSampling(unsigned int bit, int ch = -1); /// DPPAlgoritmControl bit-10:11
void SetPulsePolarity(bool PositiveIsZero, int ch = -1); /// DPPAlgoritmControl bit-16
void SetBaselineSampling(unsigned int bit, int ch = -1); /// DPPAlgoritmControl bit-20:22
void SetRollOverFlag(bool isRollOver, int ch = -1); /// DPPAlgoritmControl bit-26
void SetPileUpFlag(bool isPileUpFlag, int ch = -1); /// DPPAlgoritmControl bit-27
//int SetChannelParity(int ch, bool isPositive);
//int SetChannelThreshold(int ch, string folder, int threshold);
//int SetInputDynamicRange(int ch, string folder, int dyRange);
int SetAcqMode(string mode);
///================ Get Settings
int GetSerialNumber() {return BoardInfo.SerialNumber;}
int GetChannelMask() {return channelMask;}
float GetCh2ns() {return ch2ns;}
int GetNChannel() {return NChannel;}
int GetChTemperature(int ch) ;
void PrintBoardConfiguration();
uint32_t GetChannelStatus(unsigned int ch);
///================ ACQ control
void StopACQ();
void StartACQ();
protected:
///---- fixed parameter
int portID; /// port ID for optical link for using PCIe card, from 0, 1, 2, 3
int boardID; /// board identity
int handle; /// i don't know why, but better separete the handle from boardID
int NChannel; /// number of channel
int ADCbits; /// ADC bit
int DPPType; /// DPP verion
unsigned int ADCFullSize; /// pow(2, ADCbits) - 1
float ch2ns; /// channel to ns
CAEN_DGTZ_BoardInfo_t BoardInfo;
///----- adjustable parameters
uint32_t VMEBaseAddress; /// For direct USB or Optical-link connection, VMEBaseAddress must be 0
CAEN_DGTZ_ConnectionType LinkType;
CAEN_DGTZ_IOLevel_t IOlev; /// TTL signal (1 = 1.5 to 5V, 0 = 0 to 0.7V ) or NIM signal (1 = -1 to -0.8V, 0 = 0V)
CAEN_DGTZ_DPP_AcqMode_t AcqMode;
uint32_t channelMask ; /// the channel mask from NChannel
DigitizerChannelSetting setting[MaxNChannels];
///------- other parameters
int ret; /// return value, refer to CAEN_DGTZ_ErrorCode
bool isConnected;
///==========
virtual int ProgramBoard();
void ErrorMsg(string header = "");
};
//========================================== methods
Digitizer::Digitizer(){
portID = -1;
boardID = -1;
handle = -1;
NChannel = 0;
ADCbits = 1;
ch2ns = 0;
BoardInfo = {};
channelMask = 0xFFFF;
for( int ch = 0; ch < MaxNChannels ; ch ++ ) {
setting[ch] = {};
setting[ch].recordLength = 2000;
setting[ch].EventAggr = 0;
}
ret = -1;
isConnected = false;
VMEBaseAddress = 0;
LinkType = CAEN_DGTZ_USB; /// default USB
IOlev = CAEN_DGTZ_IOLevel_NIM; ///default NIM
AcqMode = CAEN_DGTZ_DPP_ACQ_MODE_List; ///default list mode
}
Digitizer::Digitizer(int boardID, int portID){
Digitizer();
OpenDigitizer(boardID, portID);
}
Digitizer::~Digitizer(){
CloseDigitizer();
}
void Digitizer::Reset(){
ret = CAEN_DGTZ_Reset(handle);
if( ret != 0 ) ErrorMsg("Reset");
}
int Digitizer::OpenDigitizer(int boardID, int portID){
this->boardID = boardID;
this->portID = portID;
/***************************************************/
/** Open the digitizer and read board information */
/***************************************************/
printf("============= Opening Digitizer at Board %d, Port %d \n", boardID, portID);
///-------- try USB first
LinkType = CAEN_DGTZ_USB; /// Link Type
ret = (int) CAEN_DGTZ_OpenDigitizer(LinkType, boardID, 0, VMEBaseAddress, &handle);
if (ret != 0){ ///---------- try Optical link
LinkType = CAEN_DGTZ_OpticalLink ;
ret = (int) CAEN_DGTZ_OpenDigitizer(LinkType, portID, boardID, VMEBaseAddress, &handle);
}
if (ret != 0) {
printf("Can't open digitizer\n");
}else{
///----- Getting Board Info
ret = (int) CAEN_DGTZ_GetInfo(handle, &BoardInfo);
if (ret != 0) {
printf("Can't read board info\n");
}else{
isConnected = true;
printf("Connected to Model %s with handle %d using %s\n", BoardInfo.ModelName, handle, LinkType == CAEN_DGTZ_USB ? "USB" : "Optical Link");
NChannel = BoardInfo.Channels;
channelMask = pow(2, NChannel)-1;
switch(BoardInfo.Model){
case CAEN_DGTZ_V1730: ch2ns = 2.0; break; ///ns -> 500 MSamples/s
case CAEN_DGTZ_V1725: ch2ns = 4.0; break; ///ns -> 250 MSamples/s
}
printf("Sampling rate : %.0f MHz = %.1f ns \n", 1000/ch2ns, ch2ns);
printf("Number of Channels : %d = 0x%X\n", NChannel, channelMask);
printf("SerialNumber :\e[1m\e[33m %d\e[0m\n", BoardInfo.SerialNumber);
ADCbits = BoardInfo.ADC_NBits;
ADCFullSize = (unsigned int)( pow(2, ADCbits) -1 );
printf("ADC bit is \e[33m%d\e[0m, %d = 0x%x\n", ADCbits, ADCFullSize, ADCFullSize);
printf("ROC FPGA Release is %s\n", BoardInfo.ROC_FirmwareRel);
printf("AMC FPGA Release is %s\n", BoardInfo.AMC_FirmwareRel);
int DPPType;
sscanf(BoardInfo.AMC_FirmwareRel, "%d", &DPPType);
if (DPPType != V1730_DPP_PHA_CODE) {
printf("This digitizer does not have DPP-PHA firmware\n");
}
}
}
// Check firmware revision (DPP firmwares cannot be used with this demo */
sscanf(BoardInfo.AMC_FirmwareRel, "%d", &DPPType);
if (DPPType >= 128) {
printf("\t==== This digitizer has a DPP firmware!\n");
printf("\e[32m");
switch (DPPType){
case 0x80: printf("\tDPP-PHA for x724 boards \n"); break;
case 0x82: printf("\tDPP-CI for x720 boards \n"); break;
case 0x83: printf("\tDPP-PSD for x720 boards \n"); break;
case 0x84: printf("\tDPP-PSD for x751 boards \n"); break;
case 0x85: printf("\tDPP-ZLE for x751 boards \n"); break;
case 0x86: printf("\tDPP-PSD for x743 boards \n"); break;
case 0x87: printf("\tDPP-QDC for x740 boards \n"); break;
case 0x88: printf("\tDPP-PSD for x730 boards \n"); break;
case 0x8B: printf("\tDPP-PHA for x730 boards \n"); break;
case 0x8C: printf("\tDPP-ZLE for x730 boards \n"); break;
case 0x8D: printf("\tDPP-DAW for x730 boards \n"); break;
}
printf("\e[0m");
}
int probes[MAX_SUPPORTED_PROBES];
int numProbes;
ret = CAEN_DGTZ_GetDPP_SupportedVirtualProbes(handle, 1, probes, &numProbes);
printf("\t==== supported virtual probe (number of Probe : %d)\n", numProbes);
for( int i = 0 ; i < numProbes; i++){
switch (probes[i]){
case 0: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Input\n"); break;
case 1: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Delta\n"); break;
case 2: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Delta2\n"); break;
case 3: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Trapezoid\n"); break;
case 4: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_TrapezoidReduced\n"); break;
case 5: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Baseline\n"); break;
case 6: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Threshold\n"); break;
case 7: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_CFD\n"); break;
case 8: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_SmoothedInput\n"); break;
case 9: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_None\n"); break;
case 10: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_TRGWin\n"); break;
case 11: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Armed\n"); break;
case 12: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_PkRun\n"); break;
case 13: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Peaking\n"); break;
case 14: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_CoincWin\n"); break;
case 15: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_BLHoldoff\n"); break;
case 16: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_TRGHoldoff\n"); break;
case 17: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_TRGVal\n"); break;
case 18: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_ACQVeto\n"); break;
case 19: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_BFMVeto\n"); break;
case 20: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_ExtTRG\n"); break;
case 21: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_OverThr\n"); break;
case 22: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_TRGOut\n"); break;
case 23: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Coincidence \n"); break;
case 24: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_PileUp \n"); break;
case 25: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Gate \n"); break;
case 26: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_GateShort \n"); break;
case 27: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Trigger \n"); break;
case 28: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_None \n"); break;
case 29: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_BLFreeze \n"); break;
case 30: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Busy \n"); break;
case 31: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_PrgVeto \n"); break;
}
}
ErrorMsg("end of OpenDigitizer");
if( isConnected ) {
ProgramBoard();
}
return ret;
}
int Digitizer::CloseDigitizer(){
printf("-------- Closing Digtizer Board : %d Port : %d \n", boardID, portID);
printf(" Model %s with handle %d using %s\n", BoardInfo.ModelName, handle, LinkType == CAEN_DGTZ_USB ? "USB" : "Optical Link");
ret = CAEN_DGTZ_SWStopAcquisition(handle);
ret |= CAEN_DGTZ_CloseDigitizer(handle);
return ret;
}
void Digitizer::ErrorMsg(string header){
switch (ret){
case CAEN_DGTZ_Success : /** 0 */ printf("%s | Operation completed successfully.\n", header.c_str()); break;
case CAEN_DGTZ_CommError : /** -1 */ printf("%s | Communication Error.\n", header.c_str()); break;
case CAEN_DGTZ_GenericError : /** -2 */ printf("%s | Unspecified error.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidParam : /** -3 */ printf("%s | Invalid parameter.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidLinkType : /** -4 */ printf("%s | Invalid Link Type.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidHandle : /** -5 */ printf("%s | Invalid device handler.\n", header.c_str()); break;
case CAEN_DGTZ_MaxDevicesError : /** -6 */ printf("%s | Maximum number of devices exceeded.\n", header.c_str()); break;
case CAEN_DGTZ_BadBoardType : /** -7 */ printf("%s | Operation not allowed on this type of board.\n", header.c_str()); break;
case CAEN_DGTZ_BadInterruptLev : /** -8 */ printf("%s | The interrupt level is not allowed.\n", header.c_str()); break;
case CAEN_DGTZ_BadEventNumber : /** -9 */ printf("%s | The event number is bad.\n", header.c_str()); break;
case CAEN_DGTZ_ReadDeviceRegisterFail : /** -10 */ printf("%s | Unable to read the registry.\n", header.c_str()); break;
case CAEN_DGTZ_WriteDeviceRegisterFail : /** -11 */ printf("%s | Unable to write the registry.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidChannelNumber : /** -13 */ printf("%s | The channel number is invalid.\n", header.c_str()); break;
case CAEN_DGTZ_ChannelBusy : /** -14 */ printf("%s | The channel is busy.\n", header.c_str()); break;
case CAEN_DGTZ_FPIOModeInvalid : /** -15 */ printf("%s | Invalid FPIO mode.\n", header.c_str()); break;
case CAEN_DGTZ_WrongAcqMode : /** -16 */ printf("%s | Wrong Acquistion mode.\n", header.c_str()); break;
case CAEN_DGTZ_FunctionNotAllowed : /** -17 */ printf("%s | This function is not allowed on this module.\n", header.c_str()); break;
case CAEN_DGTZ_Timeout : /** -18 */ printf("%s | Communication Timeout.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidBuffer : /** -19 */ printf("%s | The buffer is invalid.\n", header.c_str()); break;
case CAEN_DGTZ_EventNotFound : /** -20 */ printf("%s | The event is not found.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidEvent : /** -21 */ printf("%s | The event is invalid.\n", header.c_str()); break;
case CAEN_DGTZ_OutOfMemory : /** -22 */ printf("%s | Out of memory.\n", header.c_str()); break;
case CAEN_DGTZ_CalibrationError : /** -23 */ printf("%s | Unable to calibrate the board.\n", header.c_str()); break;
case CAEN_DGTZ_DigitizerNotFound : /** -24 */ printf("%s | Unbale to open the digitizer.\n", header.c_str()); break;
case CAEN_DGTZ_DigitizerAlreadyOpen : /** -25 */ printf("%s | The digitizer is already open.\n", header.c_str()); break;
case CAEN_DGTZ_DigitizerNotReady : /** -26 */ printf("%s | The digitizer is not ready.\n", header.c_str()); break;
case CAEN_DGTZ_InterruptNotConfigured : /** -27 */ printf("%s | The digitizer has no IRQ configured.\n", header.c_str()); break;
case CAEN_DGTZ_DigitizerMemoryCorrupted: /** -28 */ printf("%s | The digitizer flash memory is corrupted.\n", header.c_str()); break;
case CAEN_DGTZ_DPPFirmwareNotSupported : /** -29 */ printf("%s | The digitier DPP firmware is not supported in this lib version.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidLicense : /** -30 */ printf("%s | Invalid firmware licence.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidDigitizerStatus : /** -31 */ printf("%s | The digitizer is found in a corrupted status.\n", header.c_str()); break;
case CAEN_DGTZ_UnsupportedTrace : /** -32 */ printf("%s | The given trace is not supported.\n", header.c_str()); break;
case CAEN_DGTZ_InvalidProbe : /** -33 */ printf("%s | The given probe is not supported.\n", header.c_str()); break;
case CAEN_DGTZ_UnsupportedBaseAddress : /** -34 */ printf("%s | The base address is not supported.\n", header.c_str()); break;
case CAEN_DGTZ_NotYetImplemented : /** -99 */ printf("%s | The function is not yet implemented.\n", header.c_str()); break;
}
}
void Digitizer::PrintBoardConfiguration(){
uint32_t * value = new uint32_t[1];
CAEN_DGTZ_ReadRegister(handle, (uint32_t) Register::BoardConfiguration, value);
printf(" 32 28 24 20 16 12 8 4 0\n");
printf(" | | | | | | | | |\n");
cout <<" Board Configuration : 0b" << bitset<32>(value[0]) << endl;
printf(" Bit[ 0] = Auto Data Flush \n");
printf(" Bit[16] = WaveForm Recording \n");
printf(" Bit[17] = Extended Time Tag \n");
printf(" Bit[18] = Record Time Stamp \n");
printf(" Bit[19] = Record Energy \n");
printf("====================================== \n");
}
int Digitizer::ProgramBoard(){
ret = CAEN_DGTZ_Reset(handle);
if (ret) {
printf("ERROR: can't reset the digitizer.\n");
return -1;
}
/// Board Configuration without PHA or PSD fireware
///bx0000 0000 0000 0000 0000 0000 0001 0000 =
/// | | +- (1) trigger overlap not allowed
/// | +- (3) test pattern disable
/// + (6) Self-trigger polarity, 1 = negative, 0 = Positive
ret = CAEN_DGTZ_WriteRegister(handle, (uint32_t) Register::BoardConfiguration , 0x000E0114); /// Channel Control Reg (indiv trg, seq readout) ??
/// Set the I/O level (CAEN_DGTZ_IOLevel_NIM or CAEN_DGTZ_IOLevel_TTL)
ret |= CAEN_DGTZ_SetIOLevel(handle, IOlev);
/// Set the enabled channels
ret |= CAEN_DGTZ_SetChannelEnableMask(handle, channelMask);
/// Set the number of samples for each waveform
SetRecordLength(2000); /// default 2000 ch
///ret |= CAEN_DGTZ_SetRecordLength(handle, recordLength);
/// Set how many events to accumulate in the board memory before being available for readout
SetEventAggregation(0);
///ret |= CAEN_DGTZ_SetDPPEventAggregation(handle, EventAggr, 0);
/// Set the digitizer acquisition mode (CAEN_DGTZ_SW_CONTROLLED or CAEN_DGTZ_S_IN_CONTROLLED)
ret |= CAEN_DGTZ_SetAcquisitionMode(handle, CAEN_DGTZ_SW_CONTROLLED); /// software command
ret |= CAEN_DGTZ_SetDPPAcquisitionMode(handle, AcqMode, CAEN_DGTZ_DPP_SAVE_PARAM_EnergyAndTime);
/** Set the digitizer's behaviour when an external trigger arrives:
CAEN_DGTZ_TRGMODE_DISABLED: do nothing
CAEN_DGTZ_TRGMODE_EXTOUT_ONLY: generate the Trigger Output signal
CAEN_DGTZ_TRGMODE_ACQ_ONLY = generate acquisition trigger
CAEN_DGTZ_TRGMODE_ACQ_AND_EXTOUT = generate both Trigger Output and acquisition trigger
see CAENDigitizer user manual, chapter "Trigger configuration" for details */
ret |= CAEN_DGTZ_SetExtTriggerInputMode(handle, CAEN_DGTZ_TRGMODE_ACQ_ONLY);
/** Set the mode used to syncronize the acquisition between different boards.
In this example the sync is disabled */
ret |= CAEN_DGTZ_SetRunSynchronizationMode(handle, CAEN_DGTZ_RUN_SYNC_Disabled);
if (ret) {
ErrorMsg("End of ProgramBoard");
return ret;
} else {
return 0;
}
}
//===========================================================
void Digitizer::WriteRegister(uint32_t address, uint32_t value, int ch ){
if( ch < 0 ) {
ret = CAEN_DGTZ_WriteRegister(handle, address + 0x7000, value);
}else{
ret = CAEN_DGTZ_WriteRegister(handle, address + (ch<<8), value);
}
if( ret != 0 ) ErrorMsg("WriteRegister");
}
uint32_t Digitizer::ReadRegister(uint32_t address, unsigned int ch = 0){
uint32_t * Data = new uint32_t[NChannel];
if( ch < 0 ) {
ret = CAEN_DGTZ_ReadRegister(handle, address + 0x7000, Data);
}else{
ret = CAEN_DGTZ_ReadRegister(handle, address + (ch << 8), Data);
}
if( ret != 0 ) ErrorMsg("ReadRegister");
///printf("ch = %2d | %d \n", ch, Data[0]);
return Data[0];
}
void Digitizer::SetChannelMask(uint32_t mask){
channelMask = mask;
ret |= CAEN_DGTZ_SetChannelEnableMask(handle, channelMask);
if( ret != 0 ) ErrorMsg("SetChannelMask");
}
void Digitizer::SetRecordLength(unsigned int lenght, int ch){
if ( ch < 0 ){
for( int i = 0; i < MaxNChannels; i++ ) setting[i].recordLength = min((int)lenght, MaxRecordLength );
ret |= CAEN_DGTZ_SetRecordLength(handle, lenght);
}else{
setting[ch].recordLength = min((int)lenght, MaxRecordLength );
WriteRegister((uint32_t) RegisterDPP::RecordLength, setting[ch].recordLength, ch);
}
if( ret != 0 ) ErrorMsg("SetRecordLength");
}
void Digitizer::SetEventAggregation(unsigned int numEvent, int ch){
if( ch < 0 ){
for( int i = 0; i < MaxNChannels; i++ ) setting[i].EventAggr = numEvent;
ret |= CAEN_DGTZ_SetDPPEventAggregation(handle, numEvent, 0);
}else{
setting[ch].EventAggr = numEvent;
WriteRegister((uint32_t) RegisterDPP::NumberEventsPerAggregate, numEvent, ch);
}
if( ret != 0 ) ErrorMsg("SetEventAggregation");
}
void Digitizer::SetInputDynamicRange(unsigned int TwoVol_0_or_halfVol_1, int ch){
if( ch < 0 ) {
for( int i = 0; i < MaxNChannels; i++) setting[i].dynamicRange = TwoVol_0_or_halfVol_1;
}else{
setting[ch].dynamicRange = TwoVol_0_or_halfVol_1;
}
WriteRegister((uint32_t) Register::InputDynamicRange, TwoVol_0_or_halfVol_1, ch);
if( ret != 0 ) ErrorMsg("SetInputDynamicRange");
}
void Digitizer::SetNumSamplePreTrigger(unsigned int nSample, int ch){
if( ch < 0 ) {
for( int i = 0; i < MaxNChannels; i++) setting[i].preTrigger = nSample;
}else{
setting[ch].preTrigger = nSample;
}
WriteRegister((uint32_t) RegisterDPP::PreTrigger, nSample, ch);
if( ret != 0 ) ErrorMsg("SetNumSamplePreTrigger");
}
void Digitizer::SetDCOffset(float offsetPrecentage, int ch){
if( ch < 0 ) {
for( int i = 0; i < MaxNChannels; i++) setting[i].DCOffsetPrecentage = offsetPrecentage;
}else{
setting[ch].DCOffsetPrecentage = offsetPrecentage;
}
WriteRegister((uint32_t) RegisterDPP::ChannelDCOffset, uint( ADCFullSize * offsetPrecentage), ch );
if( ret != 0 ) ErrorMsg("SetDCOffset");
}
void Digitizer::SetVetoWidth(uint32_t bit, int ch){
if( ch < 0 ) {
for( int i = 0; i < MaxNChannels; i++) setting[i].VetoWidth = bit;
}else{
setting[ch].VetoWidth = bit;
}
WriteRegister((uint32_t) RegisterDPP::VetoWidth, bit, ch);
if( ret != 0 ) ErrorMsg("SetVetoWidth");
}
void Digitizer::SetTriggerPolarity(bool RiseingIsZero, int ch ){
if( ch < 0 ) {
ret = 0;
for (int i = 0; i < NChannel; i++){
setting[i].triggerPolarity = RiseingIsZero;
ret |= CAEN_DGTZ_SetTriggerPolarity(handle, i, CAEN_DGTZ_TriggerPolarity_t(RiseingIsZero));
}
}else{
setting[ch].triggerPolarity = RiseingIsZero;
ret = CAEN_DGTZ_SetTriggerPolarity(handle, ch, CAEN_DGTZ_TriggerPolarity_t(RiseingIsZero));
}
if( ret != 0 ) ErrorMsg("SetTriggerPolarity");
}
//============================== DPP-Alpgorthm Control
void Digitizer::SetDPPAlgorithmControl(uint32_t bit, bool useControl2, int ch){
///============= DPP algorithm control is 32 bit
/// [ 0: 5] Trapazoid Rescaling. the trapazoid ADC is 48 bit. it need to bit-shift before the 0x3FFF (14 bit filter)
/// [ 8: 9] Decimation. 00 = disable, 01 = 2 samples, 10 = 4 samples, 11 = 8 sample
/// [10:11] Decimation Gain. This gain apply to the Trapazoid Rescaling and fine gain
/// [12:13] Peak Mean. sample for averaging the trapezoid height calculation. 00 = 1 sample, 01 = 4 samples, 10 = 16 sample, 11 = 64 sample
/// [16] pulse polarity. 0 = positve, 1 = negative
/// [18:19] Trigger mode. 00 = normal, 01 = coincident, 10 = reserved. 11 = anti coincident
/// [20:22] number of samples for the baseline average calculation. 000 = baseline disable (energy not subtraced with baseline)
/// 001 = 16 samples
/// 010 = 64 samples
/// 011 = 256 samples
/// 100 = 1024 samples
/// 101 = 4096 samples
/// 110 = 16384 samples
/// 111 = resertved.
/// [24] Disable self trigger. 0 = selftrigger used to acquire and propagated to the trigger logic;
/// 1 = selftrigger only propagated to the trigger logic.
/// [26] Enable Roll-Over flag. see manual 0 = disable, 1 = enable
/// [27] Enable pile-up flag.
///============= PHA - DPP algorithm control 2 is 32 bit
/// [ 0: 1] Local Shaped Trigger mode. see manual
/// [ 2] Enable Local Shaped Trigger
/// [ 4: 5] Local Trigger Validation mode, see manual
/// [ 6] Enable Local Trigger Validation
/// [ 8:10] Extra 2 word option. 000 = [0:15] baseline *4 [16:31] extended time stamp
/// 001 = reserved
/// 010 = [0:15] fine time stamp [16:31] extended time stamp
/// 011 = reserved
/// 100 = [0:15] total tigger counter [16:31] Lost trigger counter
/// 101 = [0:15] event after the zero crosiing [16:31] event before zero crossing
/// 110, 111 = reserved.
/// [14:15] source of veto. 00 = disable, 01 veto is common to all channels, 10 = veto for coupled channels, 11 = veto comes from negative saturation
/// [16:17] Select the step for the trigger counter rate flag. see manual
/// [18] baseline calculation is active also when the acquisition is not running. 0 = disbale, 1 = enable
/// [19] Tag correlated events. see manual 0 = disbale, 1 = enable
/// [29] Enable the optimization of the Baseline Restorer to avoid tails in the energy peaks. 0 = disbale, 1 = enable
uint32_t address = (uint32_t) RegisterDPP::DPPAlgorithmControl;
if( useControl2 == true) {
if (DPPType == 0x88) address = (uint32_t) RegisterPSD::DPPAlgorithmControl2;
if (DPPType == 0x8B) address = (uint32_t) RegisterPHA::DPPAlgorithmControl2;
if (DPPType != 0x88 && DPPType != 0x8B ) {
printf(" DPP version is nto PSD or PHA, not supported. \n");
return;
}
}
if (ch < 0 ){
for( int i = 0; i < MaxNChannels; i++) setting[i].DPPAlgorithmControl = bit;
WriteRegister( address, bit);
}else{
setting[ch].DPPAlgorithmControl = bit;
WriteRegister( address, bit, ch);
}
if( ret != 0 ) ErrorMsg("SetDPPAlgorithmControl");
}
void Digitizer::SetDPPAlgorithmControlBit(unsigned int bitValue, unsigned int bitLength, unsigned int bitSmallestPos, bool useControl2, int ch){
uint32_t address = (uint32_t) RegisterDPP::DPPAlgorithmControl;
if( useControl2 == true){
if (DPPType == 0x88) address = (uint32_t) RegisterPSD::DPPAlgorithmControl2;
if (DPPType == 0x8B) address = (uint32_t) RegisterPHA::DPPAlgorithmControl2;
if (DPPType != 0x88 && DPPType != 0x8B ) {
printf(" DPP version is nto PSD or PHA, not supported. \n");
return;
}
}
uint32_t bit ;
uint32_t bitmask = (uint(pow(2, bitLength)-1) << bitSmallestPos);
if (ch < 0 ){
/// take ch-0
bit = ReadRegister(address, 0);
bit = (bit & ~bitmask) | (bitValue << bitSmallestPos);
for( int i = 0; i < MaxNChannels; i++) setting[i].DPPAlgorithmControl = bit;
}else{
bit = ReadRegister(address, ch);
bit = (bit & ~bitmask) | (bitValue << bitSmallestPos);
setting[ch].DPPAlgorithmControl = bit;
}
WriteRegister(address, bit, ch);
if( ret != 0 ) ErrorMsg("SetDPPAlgorithmControlBit");
}
void Digitizer::SetTrapezoidRescaling(unsigned int rightShiftBits, int ch ){
SetDPPAlgorithmControlBit(rightShiftBits, 5, 0, false, ch);
if( ret != 0 ) ErrorMsg("SetTrapezoidRescaling");
}
void Digitizer::SetPeakSampling(unsigned int bit, int ch){
if (ch < 0 ){
for( int i = 0; i < MaxNChannels; i++) setting[i].peakSampling = bit;
}else{
setting[ch].peakSampling = bit;
}
SetDPPAlgorithmControlBit(bit, 2, 12, false, ch);
if( ret != 0 ) ErrorMsg("SetPeakSampling");
}
void Digitizer::SetPulsePolarity(bool PositiveIsZero, int ch){
if (ch < 0 ){
for( int i = 0; i < MaxNChannels; i++) setting[i].pulsePolarity_DPP = PositiveIsZero;
}else{
setting[ch].pulsePolarity_DPP = PositiveIsZero;
}
SetDPPAlgorithmControlBit(PositiveIsZero, 1, 16, false, ch);
if( ret != 0 ) ErrorMsg("SetPulsePolarity");
}
void Digitizer::SetBaselineSampling(unsigned int bit, int ch){
if (ch < 0 ){
for( int i = 0; i < MaxNChannels; i++) setting[i].baselineSampling = bit;
}else{
setting[ch].baselineSampling = bit;
}
SetDPPAlgorithmControlBit(bit, 2, 20, false, ch);
if( ret != 0 ) ErrorMsg("SetBaselineSampling");
}
void Digitizer::SetRollOverFlag(bool isRollOver, int ch){
if (ch < 0 ){
for( int i = 0; i < MaxNChannels; i++) setting[i].rollOverFlag = isRollOver;
}else{
setting[ch].rollOverFlag = isRollOver;
}
SetDPPAlgorithmControlBit(isRollOver, 1, 26, false, ch);
if( ret != 0 ) ErrorMsg("SetRollOverFlag");
}
void Digitizer::SetPileUpFlag(bool isPileUpFlag, int ch){
if (ch < 0 ){
for( int i = 0; i < MaxNChannels; i++) setting[i].pileUpFlag = isPileUpFlag;
}else{
setting[ch].pileUpFlag = isPileUpFlag;
}
SetDPPAlgorithmControlBit(isPileUpFlag, 1, 27, false, ch);
if( ret != 0 ) ErrorMsg("SetPileUpFlag");
}
int Digitizer::SetAcqMode(string mode){
return ret;
}
int Digitizer::GetChTemperature(int ch){
if( BoardInfo.Model != CAEN_DGTZ_V1730 &&
BoardInfo.Model != CAEN_DGTZ_V1725 &&
BoardInfo.Model != CAEN_DGTZ_V1751 ) return -404;
uint32_t * temp;
ret |= CAEN_DGTZ_ReadTemperature(handle, ch, temp);
if( ret != 0 ) ErrorMsg("GetChTemperature");
return temp[0];
}
//################################################################
class DigitizerPHA : public Digitizer {
public:
DigitizerPHA();
DigitizerPHA(int boardID, int portID = 0);
~DigitizerPHA();
int ProgramBoard();
void GetChannelSetting(int ch);
};
DigitizerPHA::DigitizerPHA(){
}
DigitizerPHA::DigitizerPHA(int boardID, int portID){
OpenDigitizer(boardID, portID);
}
DigitizerPHA::~DigitizerPHA(){
}
int DigitizerPHA::ProgramBoard(){
/// Board Configuration for PHA
///bx0000 0000 0000 1110 0000 0001 0001 0100 =
/// | | |||| | | | | ||+- (0) automatic data flush, 0 = disable
/// | | |||| | | | | |+- (1) decimated smae of waveform, 0 = disable
/// | | |||| | | | | +- (2) trigger propagation, required in case of coincident trigger
/// | | |||| | | | +- (8) indivual trigger: must be 1
/// | | |||| | | + (11) dual trace. use 12:13 bit and 14:15 bit for choice of trace. but the trace recorded in half ADC frequency.
/// | | |||| | + (12:13) Analog Probe 1, 00 = input, 01 = input 1st derivative, 10 = input 2nd derivative, 11 = Trapezoid
/// | | |||| + (14:15) Analog Probe 2, 00 = input, 01 = threshold, 10 = Trapezoid - Baseline, 11 = baseline
/// | | |||+ (16) Waveform recording, 0 = disable, 1 = enable
/// | | ||+ (17) Enable Extra 2, i.e. 64 bit timestamp
/// | | |+ (18) time stamp recording: must be 1
/// | | + (19) peak recording: must be 1
/// | + (20:23) Digital Virtual probe 1: in mixed mode, virual probe can be enabled. See manual
/// + (26:28) Digitial Virtual probe 2
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t) Register::BoardConfiguration , 0x000E0114); /// Channel Control Reg (indiv trg, seq readout) ??
ErrorMsg("PHA-ProgramBoard");
return ret;
}
void DigitizerPHA::GetChannelSetting(int ch){
uint32_t * value = new uint32_t[NChannel];
printf("\e[33m================================================\n");
printf("================ Getting setting for channel %d \n", ch);
printf("================================================\e[0m\n");
///DPP algorithm Control
CAEN_DGTZ_ReadRegister(handle, 0x1080 + (ch << 8), value);
printf(" 32 28 24 20 16 12 8 4 0\n");
printf(" | | | | | | | | |\n");
cout <<" DPP algorithm Control : 0b" << bitset<32>(value[0]) << endl;
int trapRescaling = int(value[0]) & 31 ;
int polarity = int(value[0] >> 16); /// in bit[16]
int baseline = int(value[0] >> 20) ; /// in bit[22:20]
int NsPeak = int(value[0] >> 12); /// in bit[13:12]
///DPP algorithm Control 2
CAEN_DGTZ_ReadRegister(handle, 0x10A0 + (ch << 8), value);
cout <<" DPP algorithm Control 2: 0b" << bitset<32>(value[0]) << endl;
printf("* = multiple of 8 \n");
printf("** = multiple of 16 \n");
printf("==========----- input \n");
CAEN_DGTZ_ReadRegister(handle, 0x1020 + (ch << 8), value); printf("%20s %d ch \n", "Record Length", value[0] * 8); ///Record length
CAEN_DGTZ_ReadRegister(handle, 0x1038 + (ch << 8), value); printf("%20s %d ch \n", "Pre-tigger", value[0] * 4); ///Pre-trigger
printf("%20s %s \n", "polarity", (polarity & 1) == 0 ? "Positive" : "negative"); ///Polarity
printf("%20s %.0f sample \n", "Ns baseline", pow(4, 1 + baseline & 7)); ///Ns baseline
CAEN_DGTZ_ReadRegister(handle, 0x1098 + (ch << 8), value); printf("%20s %.2f %% of %d\n", "DC offset", value[0] * 100./ ADCFullSize, ADCFullSize); ///DC offset
CAEN_DGTZ_ReadRegister(handle, 0x1028 + (ch << 8), value); printf("%20s %.1f Vpp \n", "input Dynamic", value[0] == 0 ? 2 : 0.5); ///InputDynamic
printf("==========----- discriminator \n");
CAEN_DGTZ_ReadRegister(handle, 0x106C + (ch << 8), value); printf("%20s %d LSB\n", "Threshold", value[0]); ///Threshold
CAEN_DGTZ_ReadRegister(handle, 0x1074 + (ch << 8), value); printf("%20s %d ch \n", "trigger hold off *", value[0] * 8); ///Trigger Hold off
CAEN_DGTZ_ReadRegister(handle, 0x1054 + (ch << 8), value); printf("%20s %d sample \n", "Fast Dis. smoothing", value[0] ); ///Fast Discriminator smoothing
CAEN_DGTZ_ReadRegister(handle, 0x1058 + (ch << 8), value); printf("%20s %.1f ns \n", "Input rise time **", value[0] * 8 * ch2ns); ///Input rise time
printf("==========----- Trapezoid \n");
CAEN_DGTZ_ReadRegister(handle, 0x1080 + (ch << 8), value); printf("%20s %d bit = Floor( rise x decay / 64 )\n", "Trap. Rescaling", trapRescaling ); ///Trap. Rescaling Factor
CAEN_DGTZ_ReadRegister(handle, 0x105C + (ch << 8), value); printf("%20s %.1f ns \n", "Trap. rise time **", value[0] * 8 * ch2ns ); ///Trap. rise time, 2 for 1 ch to 2ns
CAEN_DGTZ_ReadRegister(handle, 0x1060 + (ch << 8), value);
int flatTopTime = value[0] * 8 * ch2ns; printf("%20s %d ns \n", "Trap. flat time **", flatTopTime); ///Trap. flat time
CAEN_DGTZ_ReadRegister(handle, 0x1068 + (ch << 8), value); printf("%20s %.1f ns \n", "Decay time **", value[0] * 8 * ch2ns); ///Trap. pole zero
CAEN_DGTZ_ReadRegister(handle, 0x1064 + (ch << 8), value); printf("%20s %.1f ns = %.2f %% \n", "peaking time **", value[0] * 8 * ch2ns, value[0] * 800. * ch2ns / flatTopTime ); //Peaking time
printf("%20s %.0f sample\n", "Ns peak", pow(4, NsPeak & 3)); //Ns peak
CAEN_DGTZ_ReadRegister(handle, 0x1078 + (ch << 8), value); printf("%20s %.1f ns \n", "Peak hole off **", value[0] * 8 *ch2ns ); ///Peak hold off
printf("==========----- Other \n");
CAEN_DGTZ_ReadRegister(handle, 0x10C4 + (ch << 8), value); printf("%20s %d \n", "Energy fine gain ?", value[0]); ///Energy fine gain
printf("========================================= end of ch-%d\n", ch);
}
//################################################################
class DigitizerPSD : public Digitizer {
public:
DigitizerPSD();
DigitizerPSD(int boardID, int portID = 0);
~DigitizerPSD();
//int ProgramBoard();
//
//void GetChannelSetting(int ch);
};
DigitizerPSD::DigitizerPSD(){
}
DigitizerPSD::DigitizerPSD(int boardID, int portID){
OpenDigitizer(boardID, portID);
}
DigitizerPSD::~DigitizerPSD(){
}
#endif