Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions iocBoot/iocCaen/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
TOP = ../..
include $(TOP)/configure/CONFIG
ARCH = linux-x86_64
#ARCH = windows-x64-static
TARGETS = envPaths
include $(TOP)/configure/RULES.ioc
33 changes: 33 additions & 0 deletions iocBoot/iocCaen/st.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!../../bin/linux-x86_64/mcaCaenApp

< envPaths

epicsEnvSet(STARTUP,$(TOP)/iocBoot/$(IOC))

dbLoadDatabase("$(MCA)/dbd/mcaCaenApp.dbd",0,0)
mcaCaenApp_registerRecordDeviceDriver(pdbbase)

# See CAENDigitizer documentation on OpenDigitizer for more info on this function
# drvCaenConfigure(Portname, LinkType, LinkNum, ConetNode, VMEBaseAddress)
drvCaenConfigure(Caen1, 5, 12345, 0, 0)

#asynSetTraceMask(Caen1, 7, 15)
#asynSetTraceIOMask(Caen1, 7, 15)
epicsEnvSet("P", "CAEN_MCA:")
epicsEnvSet("PORT", "Caen1")

# Board wide parameters
dbLoadRecords("$(MCA)/db/Caen.db","P=$(P),R=MCA01:,PORT=$(PORT)")
# Multi-ADC auxilary PVs
dbLoadRecords("$(MCA)/db/CaenBoard.db","P=$(P),M=MCA01:,PORT=$(PORT),M1=MCA01_CH01,M2=MCA01_CH02,M3=MCA01_CH03,M4=MCA01_CH04,M5=MCA01_CH05,M6=MCA01_CH06,M7=MCA01_CH07,M8=MCA01_CH08")
dbLoadRecords("$(MCA)/db/CaenChannel.db","P=$(P),R=MCA01_CH01,PORT=$(PORT),CHAN=0,NCHAN=16384,DTYP=asynMCA")
# MCA records and per-ADC parameters
dbLoadRecords("$(MCA)/db/CaenChannel.db","P=$(P),R=MCA01_CH02,PORT=$(PORT),CHAN=1,NCHAN=16384,DTYP=asynMCA")
dbLoadRecords("$(MCA)/db/CaenChannel.db","P=$(P),R=MCA01_CH03,PORT=$(PORT),CHAN=2,NCHAN=16384,DTYP=asynMCA")
dbLoadRecords("$(MCA)/db/CaenChannel.db","P=$(P),R=MCA01_CH04,PORT=$(PORT),CHAN=3,NCHAN=16384,DTYP=asynMCA")
dbLoadRecords("$(MCA)/db/CaenChannel.db","P=$(P),R=MCA01_CH05,PORT=$(PORT),CHAN=4,NCHAN=16384,DTYP=asynMCA")
dbLoadRecords("$(MCA)/db/CaenChannel.db","P=$(P),R=MCA01_CH06,PORT=$(PORT),CHAN=5,NCHAN=16384,DTYP=asynMCA")
dbLoadRecords("$(MCA)/db/CaenChannel.db","P=$(P),R=MCA01_CH07,PORT=$(PORT),CHAN=6,NCHAN=16384,DTYP=asynMCA")
dbLoadRecords("$(MCA)/db/CaenChannel.db","P=$(P),R=MCA01_CH08,PORT=$(PORT),CHAN=7,NCHAN=16384,DTYP=asynMCA")

iocInit()
90 changes: 90 additions & 0 deletions mcaApp/CaenSrc/DigitizerFunctions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include "DigitizerFunctions.h"

int ProgramDigitizer(int handle, DigitizerParams_t Params, CAEN_DGTZ_DPP_PHA_Params_t DPPParams){
/* This function uses the CAENDigitizer API functions to perform the digitizer's initial configuration */
//CAEN_DGTZ_ErrorCode ret = CAEN_DGTZ_Success;
int ret = 0;

/* Reset the digitizer */
ret |= CAEN_DGTZ_Reset(handle);

if (ret) {
printf("ERROR: can't reset the digitizer.\n");
return -1;
}
// I do not know what this does, but CAEN's example uses it
// TODO: remove this eventually?
ret |= CAEN_DGTZ_WriteRegister(handle, 0x8000, 0x01000114); // Channel Control Reg (indiv trg, seq readout) ??

ret |= CAEN_DGTZ_SetDPPAcquisitionMode(handle, Params.DPPAcqMode, Params.DPPSaveParam);
ret |= CAEN_DGTZ_SetAcquisitionMode(handle, Params.AcqMode);
ret |= CAEN_DGTZ_SetRecordLength(handle, Params.RecordLength);
ret |= CAEN_DGTZ_SetIOLevel(handle, Params.IOlev);
ret |= CAEN_DGTZ_SetExtTriggerInputMode(handle, Params.TrigMode);
ret |= CAEN_DGTZ_SetChannelEnableMask(handle, Params.ChannelMask);
ret |= CAEN_DGTZ_SetDPPEventAggregation(handle, Params.EventAggr, 0);
// TODO: create parameter for this
ret |= CAEN_DGTZ_SetRunSynchronizationMode(handle, CAEN_DGTZ_RUN_SYNC_Disabled);
ret |= CAEN_DGTZ_SetDPPParameters(handle, Params.ChannelMask, &DPPParams);

for(unsigned int i=0; i<MAX_DPP_PHA_CHANNEL_SIZE; i++) {
if (Params.ChannelMask & (1<<i)) {
ret |= CAEN_DGTZ_SetChannelDCOffset(handle, i, Params.DCOffset[i]);
ret |= CAEN_DGTZ_SetDPPPreTriggerSize(handle, i, Params.PreTriggerSize[i]);
ret |= CAEN_DGTZ_SetChannelPulsePolarity(handle, i, Params.PulsePolarity[i]);
}
}

// TODO: Implement virtual probe selection
//ret |= CAEN_DGTZ_SetDPP_VirtualProbe(handle, ANALOG_TRACE_1, CAEN_DGTZ_DPP_VIRTUALPROBE_Delta2);
//ret |= CAEN_DGTZ_SetDPP_VirtualProbe(handle, ANALOG_TRACE_2, CAEN_DGTZ_DPP_VIRTUALPROBE_None);
//ret |= CAEN_DGTZ_SetDPP_VirtualProbe(handle, DIGITAL_TRACE_1, CAEN_DGTZ_DPP_DIGITALPROBE_Peaking);

if (ret) {
printf("Warning: errors found during the programming of the digitizer.\nSome settings may not be executed\n");
return ret;
} else {
return 0;
}
}
void SetDefaultParams(DigitizerParams_t * Params, CAEN_DGTZ_DPP_PHA_Params_t * DPPParams){
Params->IOlev = CAEN_DGTZ_IOLevel_NIM;
Params->DPPAcqMode = CAEN_DGTZ_DPP_ACQ_MODE_List; // TODO: Maybe consider CAEN_DGTZ_DPP_ACQ_MODE_Mixed
Params->DPPSaveParam = CAEN_DGTZ_DPP_SAVE_PARAM_EnergyAndTime;
Params->AcqMode = CAEN_DGTZ_SW_CONTROLLED;
Params->RecordLength = 50000; // Only needed for Mixed/Scope mode
Params->ChannelMask = (1<<8) - 1; // Enable 8 channels
// Params->ChannelMask = (1<<MAX_DPP_PHA_CHANNEL_SIZE) - 1; // Enable all channels
Params->EventAggr = 0; // 0 = Auto
Params->TrigMode = CAEN_DGTZ_TRGMODE_ACQ_ONLY;

for(unsigned int ch = 0; ch < MAX_DPP_PHA_CHANNEL_SIZE; ch++) {
Params->PulsePolarity[ch] = CAEN_DGTZ_PulsePolarityPositive;
Params->PreTriggerSize[ch] = 1000;
Params->DCOffset[ch] = 0x8000;
DPPParams->thr[ch] = 100; // Trigger Threshold (in LSB)
DPPParams->k[ch] = 3000; // Trapezoid Rise Time (ns)
DPPParams->m[ch] = 900; // Trapezoid Flat Top (ns)
DPPParams->M[ch] = 25000; // Decay Time Constant (ns)
DPPParams->ftd[ch] = 500; // Flat top delay (peaking time) (ns)
DPPParams->a[ch] = 4; // Trigger Filter smoothing factor (number of samples to average for RC-CR2 filter) Options: 1; 2; 4; 8; 16; 32
DPPParams->b[ch] = 200; // Input Signal Rise time (ns)
DPPParams->trgho[ch] = 1200; // Trigger Hold Off
DPPParams->nsbl[ch] = 4; //number of samples for baseline average calculation. Options: 1->16 samples; 2->64 samples; 3->256 samples; 4->1024 samples; 5->4096 samples; 6->16384 samples
DPPParams->nspk[ch] = 0; //Peak mean (number of samples to average for trapezoid height calculation). Options: 0-> 1 sample; 1->4 samples; 2->16 samples; 3->64 samples
DPPParams->pkho[ch] = 2000; //peak holdoff (ns)
DPPParams->blho[ch] = 500; //Baseline holdoff (ns)
DPPParams->enf[ch] = 1.0; // Energy Normalization Factor
DPPParams->decimation[ch] = 0; //decimation (the input signal samples are averaged within this number of samples): 0 ->disabled; 1->2 samples; 2->4 samples; 3->8 samples
DPPParams->dgain[ch] = 0; //decimation gain. Options: 0->DigitalGain=1; 1->DigitalGain=2 (only with decimation >= 2samples); 2->DigitalGain=4 (only with decimation >= 4samples); 3->DigitalGain=8( only with decimation = 8samples).
DPPParams->otrej[ch] = 0; // Deprecated
DPPParams->trgwin[ch] = 0; //Enable Rise time Discrimination. Options: 0->disabled; 1->enabled
DPPParams->twwdt[ch] = 100; //Rise Time Validation Window (ns)
//DPPParams.tsampl[ch] = 10;
//DPPParams.dgain[ch] = 1;
}
}

unsigned long long int get_time_ns(){
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
11 changes: 11 additions & 0 deletions mcaApp/CaenSrc/DigitizerFunctions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "ParamStruct.h"
#include <CAENDigitizerType.h>
#include <CAENDigitizer.h>
#include <cstdio>
#include <chrono> // Needed for get_time_ms (requires C++11)

int ProgramDigitizer(int handle, DigitizerParams_t Params, CAEN_DGTZ_DPP_PHA_Params_t DPPParams);

void SetDefaultParams(DigitizerParams_t * Params, CAEN_DGTZ_DPP_PHA_Params_t * DPPParams);

unsigned long long int get_time_ns();
67 changes: 67 additions & 0 deletions mcaApp/CaenSrc/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
TOP=../..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================
PYDEVSUP ?= /etc/epics
PYTHON ?= python3
include $(PYDEVSUP)/configure/CONFIG_PY

#=============================

# <name>.dbd will be created from <name>Include.dbd
DBD += mcaCaenApp.dbd
mcaCaenApp_DBD +=
DBD += mcaCaenSupport.dbd

# I only have a Linux environment to test
LIBRARY_IOC += mcaCaen
PROD_IOC += mcaCaenApp

# Include where CAENDigitizer.h is
USR_INCLUDES += -I/usr/include/

## <name>_registerRecordDeviceDriver.cpp will be created from <name>.dbd
#mcaCaen_SRCS += NetFinder.cpp

mcaCaen_SRCS += drvCaen.cpp

mcaCaen_LIBS += asyn
mcaCaen_LIBS += $(EPICS_BASE_IOC_LIBS)
#mcaCaen_SYS_LIBS += usb-1.0
#mcaCaen_LIBS_WIN32 += libusb-1.0

## <name>_registerRecordDeviceDriver.cpp will be created from <name>.dbd
mcaCaenApp_SRCS += mcaCaenApp_registerRecordDeviceDriver.cpp
mcaCaenApp_SRCS += DigitizerFunctions.cpp
mcaCaenApp_SRCS_DEFAULT += mcaCaenAppMain.cpp
mcaCaenApp_SRCS_vxWorks += -nil-
mcaCaenApp_LIBS += mcaCaen
mcaCaenApp_LIBS += mca
mcaCaenApp_LIBS += calc autosave
mcaCaenApp_LIBS += sscan busy
mcaCaenApp_LIBS += asyn
mcaCaenApp_LIBS += seq pv
mcaCaenApp_LIBS += pyDevSup$(PY_LD_VER)
mcaCaenApp_LIBS += $(EPICS_BASE_IOC_LIBS)
mcaCaenApp_SYS_LIBS += CAENDigitizer
#mcaCaenApp_SYS_LIBS += usb-1.0
#mcaCaenApp_LIBS_WIN32 += libusb-1.0

mcaCaenApp_DBD += base.dbd
mcaCaenApp_DBD += mcaCaenSupport.dbd
mcaCaenApp_DBD += mcaSupport.dbd
mcaCaenApp_DBD += asyn.dbd
mcaCaenApp_DBD += drvAsynIPPort.dbd
mcaCaenApp_DBD += calcSupport.dbd
mcaCaenApp_DBD += asSupport.dbd
mcaCaenApp_DBD += busySupport.dbd
mcaCaenApp_DBD += sscanSupport.dbd
mcaCaenApp_DBD += pyDevSup.dbd
mcaCaenApp_DBD += system.dbd

DIAGSTD ?= $(EPICS_BASE)
include $(DIAGSTD)/configure/fribdiagstdMakefile
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE
24 changes: 24 additions & 0 deletions mcaApp/CaenSrc/ParamStruct.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "CAENDigitizerType.h"

#ifndef PARAM_STRUCTS
#define PARAM_STRUCTS
typedef struct
{
CAEN_DGTZ_ConnectionType LinkType;
uint32_t VMEBaseAddress;
uint32_t LinkNum;
uint32_t ConetNode;
uint32_t RecordLength;
uint32_t ChannelMask;
int EventAggr;
CAEN_DGTZ_PulsePolarity_t PulsePolarity[MAX_DPP_PHA_CHANNEL_SIZE];
uint32_t DCOffset[MAX_DPP_PHA_CHANNEL_SIZE];
uint32_t PreTriggerSize[MAX_DPP_PHA_CHANNEL_SIZE];
CAEN_DGTZ_AcqMode_t AcqMode;
CAEN_DGTZ_DPP_SaveParam_t DPPSaveParam;
CAEN_DGTZ_DPP_AcqMode_t DPPAcqMode;
CAEN_DGTZ_TriggerMode_t TrigMode;
CAEN_DGTZ_IOLevel_t IOlev;
} DigitizerParams_t;

#endif
8 changes: 8 additions & 0 deletions mcaApp/CaenSrc/TODO
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- Add way to resize buffers?
- Some parameters are still hard-coded
- Make poll period account for thread run time
- Initialize parameters in constructor or connectDevice
- Investigate how to measure live-time (perhaps discard one event and use the difference between the first and last event as elapsed time?)
- Implement PCTL and PCTH for PresetCounts
- Lean out read thread removing time tag processing
- Implement reading of pile-up events
Loading