FSUDAQ/DAQ/Acquisition.cpp
2023-02-08 12:00:30 -05:00

296 lines
12 KiB
C++

#include "macro.h"
#include "ClassData.h"
#include "ClassDigitizer.h"
#include "influxdb.h"
#include <condition_variable>
#include <mutex>
#include <sys/time.h> /** struct timeval, select() */
#include <termios.h> /** tcgetattr(), tcsetattr() */
#include <vector>
#include <thread>
#include "TString.h"
#include "TSystem.h"
#include <iostream>
#include <fstream>
#define nDig 4
Digitizer * dig[4];
std::mutex mtx[nDig];
std::condition_variable cv;
bool ready = false;
bool stop_acquisition = false;
timespec ts[nDig];
static struct termios g_old_kbd_mode;
char* path_to_run="/home/bavarians/FSUDAQ_MUSIC/Run/";
char* path_to_DAQ="/home/bavarians/FSUDAQ_MUSIC/";
static void cooked(void){
tcsetattr(0, TCSANOW, &g_old_kbd_mode);
}
static void uncooked(void){
struct termios new_kbd_mode;
/** put keyboard (stdin, actually) in raw, unbuffered mode */
tcgetattr(0, &g_old_kbd_mode);
memcpy(&new_kbd_mode, &g_old_kbd_mode, sizeof(struct termios));
new_kbd_mode.c_lflag &= ~(ICANON | ECHO);
new_kbd_mode.c_cc[VTIME] = 0;
new_kbd_mode.c_cc[VMIN] = 1;
tcsetattr(0, TCSANOW, &new_kbd_mode);
}
static void raw(void){
static char init;
if(init) return;
/** put keyboard (stdin, actually) in raw, unbuffered mode */
uncooked();
/** when we exit, go back to normal, "cooked" mode */
atexit(cooked);
init = 1;
}
int keyboardhit(){
struct timeval timeout;
fd_set read_handles;
int status;
raw();
/** check stdin (fd 0) for activity */
FD_ZERO(&read_handles);
FD_SET(0, &read_handles);
timeout.tv_sec = timeout.tv_usec = 0;
status = select(0 + 1, &read_handles, NULL, NULL, &timeout);
if(status < 0){
printf("select() failed in keyboardhit()\n");
exit(1);
}
return (status);
}
int getch(void){
unsigned char temp;
raw();
/** stdin = fd 0 */
if(read(0, &temp, 1) != 1) return 0;
return temp;
}
void go() {
ready = true;
cv.notify_all();
}
void func(Digitizer * dig, double RunTime, int Rid, int Bid){
std::unique_lock<std::mutex> lck(mtx[Bid]);
while (!ready ){
printf("waiting for unlock %d\n", Bid);
cv.wait(lck);
}
cv.notify_all();
clock_gettime(CLOCK_REALTIME, &ts[Bid]);
printf("----thread %d ready. %ld ns\n", Bid, ts[Bid].tv_nsec);
dig->StartACQ();
if(RunTime>0){
unsigned long time;
unsigned long time0 = get_time();
do{
usleep(5*1000);
dig->ReadData();
dig->GetData()->DecodeBuffer(true,0);
//dig->GetData()->PrintStat();
//dig->GetData()->PrintData();
gSystem->cd(path_to_run);
dig->GetData()->SaveBuffer(Form("Run_%03u_B%01u",Rid, Bid));
time = get_time();
//printf("********************* time : %lu usec\n", time-time0);
}
while((time-time0)*1e-6<=(RunTime));
time = get_time();
//printf("********************* end time : %lu usec\n", time-time0);
dig->StopACQ();
}
if(RunTime<=0){
do{
usleep(5*1000);
dig->ReadData();
unsigned long time1 = get_time();
dig->GetData()->DecodeBuffer(true,0);
unsigned long time2 = get_time();
//dig->GetData()->PrintStat();
//dig->GetData()->PrintData();
gSystem->cd(path_to_run);
dig->GetData()->SaveBuffer(Form("Run_%03u_B%01u",Rid, Bid));
}
while(RunTime<=0 && !stop_acquisition);
dig->StopACQ();
}
printf("thread %d finished.\n", Bid);
}
void boardSetParameters(int BI, Digitizer * dig, double BoardConfigurationval, double DPPAlgoCtrl, double DPPAlgoCtrl_10A0,double DPPAlgoCtrl_10AC, double ShapedTriggerWidthVal, double InputSec[7], double DiscriSec[4], double TrapSec[7]){
//ALL channels
//GENERAL
dig->WriteRegister(Register::DPP::BoardConfiguration, BoardConfigurationval); //Reg=0x8000
dig->WriteRegister(Register::DPP::DPPAlgorithmControl, DPPAlgoCtrl);//Reg=0x1080
dig->WriteRegister(Register::DPP::PHA::DPPAlgorithmControl2_G, DPPAlgoCtrl_10A0); //Reg=0x10A0
dig->WriteRegister(Register::DPP::PHA::DPPAlgorithmControl22_G, DPPAlgoCtrl_10AC); //Reg=0x10AC
//Input Section
dig->WriteRegister(Register::DPP::RecordLength_G, InputSec[1]); //Reg=0x1020
//Syncrhonization Section
//Trigger/Veto/coinc Section
dig->WriteRegister(Register::DPP::PHA::ShapedTriggerWidth, ShapedTriggerWidthVal); //Reg=0x1084
//Miscellaneaous Section
//per channel
for(int i=0;i<16;i++){
//GENERAL
//Input Section
dig->WriteRegister(Register::DPP::PreTrigger, InputSec[2], i);//Reg=0x1038
dig->WriteRegister(Register::DPP::ChannelDCOffset, InputSec[5], i);//Reg=0x1098
dig->WriteRegister(Register::DPP::InputDynamicRange, InputSec[6], i);//Reg=0x1028
//Discriminator Section
dig->WriteRegister(Register::DPP::PHA::TriggerThreshold,DiscriSec[0], i);//Reg=0x106C
dig->WriteRegister(Register::DPP::PHA::TriggerHoldOffWidth, DiscriSec[1], i);//Reg=0x1074
dig->WriteRegister(Register::DPP::PHA::RCCR2SmoothingFactor,DiscriSec[2], i);//Reg=0x1054
dig->WriteRegister(Register::DPP::PHA::InputRiseTime, DiscriSec[3], i);//Reg=0x1058
//Trapezoid Section
dig->WriteRegister(Register::DPP::PHA::TrapezoidRiseTime,TrapSec[0], i);//Reg=0x105C
dig->WriteRegister(Register::DPP::PHA::TrapezoidFlatTop, TrapSec[1], i);//Reg=0x1060
dig->WriteRegister(Register::DPP::PHA::DecayTime, TrapSec[2], i);//Reg=0x1068
dig->WriteRegister(Register::DPP::PHA::PeakingTime,TrapSec[3], i);//Reg=0x1064
dig->WriteRegister(Register::DPP::PHA::PeakHoldOff,TrapSec[5], i);//Reg=0x1078
dig->WriteRegister(Register::DPP::PHA::FineGain,TrapSec[6], i);//Reg=0x10C4
}
}
void boardCommonParameters(Digitizer * dig){
//all channels
dig->WriteRegister(Register::DPP::TriggerValidationMask_G , 0x00000000);//Reg=0x8100
//per channels
for(int i=0;i<16;i++){
dig->WriteRegister(Register::DPP::PHA::RiseTimeValidationWindow, 0x00000000, i);//Reg=0x1070
dig->WriteRegister(Register::DPP::VetoWidth, 0x0000000A, i);//Reg=0x10D4
dig->WriteRegister(Register::DPP::Scratch, 0xAAAAAAAA, i);//Reg=0xEF20
dig->WriteRegister(Register::DPP::InterruptEventNumber, 0x00000000,i);//Reg=0xEF18
dig->WriteRegister(Register::DPP::InterruptStatusID, 0x000000DD,i);//Reg=0xEF14
dig->WriteRegister(Register::DPP::RelocationAddress, 0x00000000,i);//Reg=0xEF10
dig->WriteRegister(Register::DPP::MCSTBaseAddressAndControl , 0x000000AA, i);//Reg=0xEF0C
dig->WriteRegister(Register::DPP::ReadoutControl, 0x00000010, i);//Reg=0xEF00
dig->WriteRegister(Register::DPP::ExtendedVetoDelay, 0x12340014,i);//Reg=0x81C4
dig->WriteRegister(Register::DPP::BufferOccupancyGain , 0x00000000, i);//Reg=0x81B4
dig->WriteRegister(Register::DPP::FrontPanelLVDSIONewFeatures , 0x00001111, i);//Reg=0x81A0
dig->WriteRegister(Register::DPP::RunStartStopDelay , 0x00000000, i);//Reg=0x8170
dig->WriteRegister(Register::DPP::DisableExternalTrigger, 0x00000000,i);//Reg=0x817C
dig->WriteRegister(Register::DPP::FanSpeedControl, 0x00000020, i);//Reg=0x8168
dig->WriteRegister(Register::MemoryBufferAlmostFullLevel, 0x00000000, i);//Reg=0x816C
dig->WriteRegister(Register::DPP::AcquisitionControl, 00000000,i);//Reg=0x8100
dig->WriteRegister(Register::DPP::GlobalTriggerMask, 0x80000000,i);//Reg=0x810C
dig->WriteRegister(Register::DPP::FrontPanelTRGOUTEnableMask, 0x00000000, i);//Reg=0x8110
dig->WriteRegister(Register::DPP::LVDSIOData, 0x0000FFFF, i);//Reg=0x8118
dig->WriteRegister(Register::DPP::FrontPanelIOControl, 0x00008100, i);//Reg=0x811C
dig->WriteRegister(Register::DPP::ChannelEnableMask, 0x0000FFFF, i);//Reg=0x8120
dig->WriteRegister(Register::DPP::VoltageLevelModeConfig, 0x00000000, i);//Reg=0x8138
dig->WriteRegister(Register::DPP::AnalogMonitorMode, 0x00000000, i);//Reg=0x8144
}
}
int main(int argc, char* argv[]){
printf("=====================================\n");
printf("=== FSU DAQ ===\n");
printf("=====================================\n");
if (argc < 2) {
printf("Incorrect number of arguments:\n");
printf("%s [RunTime] [RunId] \n", argv[0]);
printf(" RunTime in sec, default = -1 if unstoppped \n");
return 1;
}
double RunTime = atoi(argv[1]);
int Rid= atoi(argv[2]);
//""""""""""""""""""""""""""""""
//Opening digitizers
//""""""""""""""""""""""""""""""
for(int d=0;d<nDig;d++){
dig[d] = new Digitizer(0, d, false, true);
}
//""""""""""""""""""""""""""""""
//Register value assignment
//""""""""""""""""""""""""""""""
double BoardConfigurationval[4] ={0x014E8905,0x014E0105,0x014E0105,0x014E0105}; //Reg=8000
double DPPAlgoCtrl[4] ={0x0831200E,0x0831200E,0x0831200E,0x0831200E}; //Reg=1080
double DPPAlgoCtrl_10A0[4] ={0x00000000,0x00000000,0x00000000,0x00000000}; //Reg=10A0
double DPPAlgoCtrl_10AC[4] ={0x0010010E,0x0010010E,0x0010010E,0x0010010E}; //Reg=10AC
double ShapedTriggerWidthVal = 6; //Reg=1084 in steps of 16ns
//1==RecordLength input N such length (ns) == N*8*4 , 2==PreTrigger input N such length (ns) == N*4*4
//5==DCoffset DC% = 1 - input/65535, 6==CoarseGain 0=x1 or 1=x4
double InputSec[4][7] ={ {0, 375, 200,0,0,0x00004CCC, 0},
{0, 375, 200,0,0,0x00004CCC, 0},
{0, 375, 200,0,0,0x00004CCC, 0},
{0, 375, 200,0,0,0x00004CCC, 0}};
//0==TriggerThreshold in lsb, 1==TriggerHoldOffWidth in steps of 16ns, 2==FastDiscriSmooth (20=64samp, 63=128samp),
// 3==InputRiseTime in steps of 16ns, 144=9*16 ns
double DiscriSec[4][4]={ {100, 30, 63, 56},
{100, 30, 63, 56},
{100, 30, 63, 56},
{100, 30, 63, 56}};
//0==RiseTime in steps of 16ns, 496=31*16, 1==FlatTop in steps of 16ns, 2=PoleZero in steps of 16ns
//3==PeakingTime in steps of 16ns, 60% of flat top, 5==PeakHoldOff in steps of 16ns, fine gain 1==0x00006C3A
double TrapSec[4][7]={{31, 187, 625,94, 0, 62, 0x00006C3A},
{31, 187, 625,94, 0, 62, 0x00006C3A},
{31, 187, 625,94, 0, 62, 0x00006C3A},
{31, 187, 625,94, 0, 62, 0x00006C3A}};
for( int i = 0; i < nDig; i++){
dig[i]->ProgramPHABoard();
dig[i]->ReadAllSettingsFromBoard();
dig[i]->WriteRegister(Register::DPP::SoftwareClear_W, 1);
dig[i]->WriteRegister(Register::DPP::MaxAggregatePerBlockTransfer, 40);//80 Reg=0xEF1C
dig[i]->WriteRegister(Register::DPP::NumberEventsPerAggregate_G, 511);//1023-->forced in WriteRegisterFromFile Reg=0x1034
printf("========== %d \n", dig[i]->ReadSettingFromFile(Register::DPP::MaxAggregatePerBlockTransfer));
boardSetParameters(i, dig[i], BoardConfigurationval[i],DPPAlgoCtrl[i], DPPAlgoCtrl_10A0[i],DPPAlgoCtrl_10AC[i], ShapedTriggerWidthVal, InputSec[i], DiscriSec[i], TrapSec[i] );
boardCommonParameters(dig[i]);
dig[i]-> SaveAllSettingsAsText(Form("reg_Board%i.txt",i));
dig[i]->GetData()->SetSaveWaveToMemory(false);
}
//""""""""""""""""""""""""""""""
//Parallel digitizer data taking
//""""""""""""""""""""""""""""""
std::thread fdig[nDig];
for (int i = 0; i < nDig; ++i){
fdig[i] = std::thread(func, dig[i],RunTime , Rid, i);
}
printf("%d threads ready to race...\n", nDig);
usleep(1000*1000);
if(RunTime<=0){
printf("Enter to stop ..\n");
if(getchar()){stop_acquisition=true;}
}
go();
for (auto& f : fdig) f.join();
printf("=========== finsihed.\n");
long avg = 0;
for( int i =0; i < nDig ; i++) avg += ts[i].tv_nsec;
avg = avg/nDig;
long min , max;
for( int i =0; i < nDig; i++) {
if( i == 0 ){
min = ts[i].tv_nsec;
max = ts[i].tv_nsec;
continue;
}
if( min > ts[i].tv_nsec) min = ts[i].tv_nsec;
if( max < ts[i].tv_nsec) max = ts[i].tv_nsec;
}
printf(" avg : %ld\n", avg);
printf(" min : %ld, %ld\n", min, avg - min);
printf(" max : %ld, %ld\n", max, max - avg);
printf(" diff : %ld\n", max-min);
for(int i=0;i<nDig;i++){delete dig[i];}
return 0;
}