--- /dev/null
+<?xml version="1.0"?>
+
+<!--
+This is example file how HADAQ event building should be configured in DABC.
+Event building process implemented in Combiner module of hadaq::CombinerModule class.
+Module can have several inputs, each with separate port number for receiving data
+from TRB boards. In each input port configuration only port number has meaning.
+First output of combiner module reserved for the connection to
+the optional MBS transmitter module. Second output can be use to store data in hld files.
+To enable storage, one should specify two output ports and correctly configure Output1 of combiner module.
+
+Optionally one can enable MBS transmitter module, which converts HLD to LMD format.
+To enable transmitter, one should specify auto="true" in configuration which says DABC
+to automatically create module when starting application.
+First output of the module reserved for stream server, second output can be used to
+store data in lmd files.
+
+-->
+
+<dabc version="2">
+ <Context host="localhost" name="EventBuilder">
+ <Run>
+ <lib value="libDabcMbs.so"/>
+ <lib value="libDabcHadaq.so"/>
+ <logfile value="hadaqevtbuild.log"/>
+ <loglimit value="1000000"/>
+ <!--affinity value="-1"/-->
+ </Run>
+
+ <MemoryPool name="Pool">
+ <BufferSize value="200000"/>
+ <NumBuffers value="1000"/>
+ </MemoryPool>
+
+ <Module name="Combiner" class="hadaq::CombinerModule">
+ <!-- these parameters will force to create inputs/oputputs of module -->
+ <NumInputs value="1"/>
+ <NumOutputs value="1"/>
+
+ <InputPort name="Input0" url="hadaq://host:50000"/>
+ <InputPort name="Input1" url="hadaq://host:10102"/>
+ <InputPort name="Input2" url="hadaq://host:10103"/>
+ <InputPort name="Input3" url="hadaq://host:10104"/>
+ <InputPort name="Input4" url="hadaq://host:10105"/>
+
+ <InputPort name="Input*" queue="10">
+ <HadaqUdpBuffer value="200000"/>
+ <DoShmControl value="false"/>
+ <HadaqUdpMTU value="64512"/>
+ <FlushTimeout value="2.0"/>
+ </InputPort>
+
+ <OutputPort name="Output1" url="hld://dabc.hld?maxsize=30"/>
+
+ <DoShmControl value="false"/>
+ <FlushTimeout value="2.0"/>
+
+ <!-- take event sequence number from vulom/roc sync message at cts -->
+ <UseSyncSequenceNumber value="false"/>
+ <SyncSubeventId value="0x8000"/>
+ <SyncTriggerMask value="0x01"/>
+ <PrintSync value="false"/>
+ <FlushBySync value="false"/>
+
+ <!-- rate meters configuration -->
+ <HadaqData width="4" prec="2" low="0" up="10" debug="1"/>
+ <HadaqEvents width="5" prec="1" low="0" up="1000" debug="1"/>
+ <HadaqDroppedData width="5" prec="3" low="0" up="1" debug="1"/>
+ <HadaqLostEvents width="4" prec="2" low="0" up="100" debug="1"/>
+ </Module>
+
+ <Module name="OnlineServer" class="hadaq::MbsTransmitterModule" auto="true">
+ <NumInputs value="1"/>
+ <NumOutputs value="1"/>
+
+ <InputPort name="Input0" url="Combiner/Output0" queue="10"/>
+
+ <OutputPort name="Output0" url="mbs://Stream"/>
+ <OutputPort name="Output1" url="lmd://test.lmd?maxsize=30&log=2"/>
+
+ <!-- this is 32-bit MBS subevent id, which than can be seen in the analysis. Here procid=0x1f is configured -->
+ <SubeventFullId value="0x000001F"/>
+
+ <!-- If true, all events with the same SYNC number will be merged together into same MBS event -->
+ <DoMergeSyncedEvents value="true"/>
+
+ <TransmitData width="5" prec="3" low="0" up="50" debug="1"/>
+ <TransmitEvents width="4" prec="1" low="0" up="100" debug="1"/>
+ </Module>
+
+ </Context>
+
+ <!--Context name="*">
+ <Thread name="CombinerThrdInp" class="dabc::SocketThread" affinity="+0"/>
+ </Context-->
+
+</dabc>
--- /dev/null
+// Automatically generated startup script
+// Do not change it!
+
+go4->SetMainWindowState(4,"000000ff00000000fd0000000200000000000001c0000002c4fc0200000001fb0000001600420072006f00770073006500720044006f0063006b0100000055000002c40000007900ffffff00000003000003d5000000d5fc0100000001fc00000000000003d50000000000fffffffa000000020200000003fb00000016004c006f00670049006e0066006f0044006f0063006b0000000000ffffffff0000005200fffffffb0000001a004d006200730056006900650077006500720044006f0063006b0000000000ffffffff0000006400fffffffb0000001e0044004100420043004d006f006e00690074006f00720044006f0063006b0000000279000000ce0000000000000000000003da000002c400000004000000040000000800000008fc0000000800000002000000040000001600460069006c00650054006f006f006c0042006100720100000000ffffffff0000000000000000000000160047006f00340054006f006f006c007300420061007201000000e7ffffffff00000000000000000000001e0041006e0061006c00790073006900730054006f006f006c004200610072010000022b0000025800000000000000000000001a0044006900760069006400650050006100640044006f0063006b0000000395000000e40000000000000000000000020000000000000002000000020000002400420072006f0077007300650072004f007000740069006f006e00730044006f0063006b01000000000000010200000000000000000000001e0044007200610077004f007000740069006f006e00730044006f0063006b01000001020000037e00000000000000000000000200000002000000240048006900730044007200610077004f007000740069006f006e00730044006f0063006b0000000000000001290000000000000000000000180047006f0034005300740079006c00650044006f0063006b0000000000000004b10000000000000000000000020000000100000020005300630061006c0065004f007000740069006f006e00730044006f0063006b0000000000000004b10000000000000000000000030000000000000003000000010000001e0043006f006d006d0061006e0064004c0069006e00650044006f0063006b0000000000000004b1000000000000000000000003000000010000001c00540072006500650056006900650077006500720044006f0063006b0000000000000004b10000000000000000");
+go4->SetMainWindowGeometry(4,"01d9d0cb0001000000000000000000000000059f0000034f0000000000000000fffffffefffffffe000000000200");
+
+go4->LaunchAnalysis("MyAnalysis", ".", "libGo4UserAnalysis", "localhost", Go4_sh, Go4_qt, Go4_lib);
+go4->WaitAnalysis(300);
+
+// configuration of analysis
+go4->AnalysisAutoSave("Go4AutoSave.root", 500, 5, kTRUE, kFALSE);
+go4->AnalysisConfigName("Go4AnalysisPrefs.root");
+
+// step Analysis
+go4->ConfigStep("Analysis", kTRUE, kTRUE, kFALSE);
+go4->StepMbsStreamSource("Analysis", "localhost", 1);
+go4->StepFileStore("Analysis", "NoOutputDefined", kTRUE, 32000, 99, 5);
+
+go4->SubmitAnalysisConfig(20);
+
+go4->SetAnalysisConfigMode(-1);
+go4->SetAnalysisTerminalMode(-1);
+
+go4->StartAnalysis();
+
+// this is possibility to get extra histograms from analysis
+// which are create shortly after analysis is started
+go4->Wait(1);
+go4->RefreshNamesList();
+
+go4->MonitorItem("Analysis/Histograms");
--- /dev/null
+void first()
+{
+
+ base::ProcMgr::instance()->SetRawAnalysis(true);
+
+ hadaq::TdcMessage::SetFineLimits(31, 421);
+
+ hadaq::TrbProcessor* trb3 = new hadaq::TrbProcessor(0);
+
+ // CTS subevent header id, all 16 bit
+ // trb3->SetHadaqCTSId(0x8000);
+
+ // HUB subevent header id, here high 8 bit from 16 should be specified
+ // lower 8 bit are used as hub number
+ trb3->SetHadaqHUBId(0x9000);
+
+ trb3->SetPrintRawData(false);
+
+ // set number of errors to be printed, default 1000
+ trb3->SetPrintErrors(100);
+
+
+ // enable cross processing only when one want to specify reference channel from other TDCs
+ // in this case processing 'crosses' border of TDC and need to access data from other TDC
+ // trb3->SetCrossProcess(true);
+
+ // this is array with available TDCs ids
+ // It is required that high 8 bits are the same.
+ // These bits are used to separate TDC data from other data kinds
+
+ int tdcmap[4] = { 0x0310, 0x0311, 0x0312, 0x0313 };
+
+ // TDC subevent header id
+ trb3->SetHadaqTDCId(tdcmap[0] & 0xFF00);
+
+ for (int cnt=0;cnt<4;cnt++) {
+
+ int tdcid = tdcmap[cnt] & 0x00FF;
+
+ // verify prefix
+ if ((tdcmap[0] & 0xFF00) != (tdcmap[cnt] & 0xFF00)) {
+ fprintf(stderr, "!!!! Wrong prefix in TDC%d, do not match with TDC0 %X != %X\n", cnt, (tdcmap[cnt] & 0xFF00), (tdcmap[0] & 0xFF00));
+ exit(5);
+ }
+
+ // create processor for hits from TDC
+ // par1 - pointer on trb3 board
+ // par2 - TDC number (lower 8 bit from subevent header
+ // par3 - number of channels in TDC
+ // par4 - edges mask 0x1 - rising, 0x2 - trailing, 0x3 - both edges
+ hadaq::TdcProcessor* tdc = new hadaq::TdcProcessor(trb3, tdcid, 65, 0x1);
+
+ if (cnt==0) {
+ int channels[] = {33, 34, 35, 36, 0};
+ tdc->CreateHistograms( channels );
+
+ tdc->SetRefChannel(34, 0, 0xffff, 10000, -500., 500., true);
+ //tdc->SetRefChannel(35, 34, 0xffff, 10000, -500., 500., true);
+
+ //tdc->SetRefChannel(36, 35, 0xffff, 10000, -500., 500., true);
+
+ tdc->SetRefChannel(35, 33, 0xffff, 10000, -10., 400., true);
+ tdc->SetRefChannel(36, 35, 0xffff, 10000, -10., 400., true);
+ // IMPORTANT: for both channels references should be already specified
+ tdc->SetDoubleRefChannel(36, 35, 1000, -10., 500., 1000, -10., 200.);
+ }
+
+ if (cnt==3) {
+ int channels[] = {1, 2, 3, 4, 0};
+ tdc->CreateHistograms( channels );
+ tdc->SetRefChannel(1, 3, 0xffff, 10000, -50., 50., true);
+ tdc->SetRefChannel(2, 4, 0xffff, 10000, -50., 50., true);
+
+ }
+
+
+ // specify reference channel for any other channel -
+ // will appear as additional histogram with time difference between channels
+ // for (int n=2;n<65;n=n+2)
+ // tdc->SetRefChannel(n, n-1);
+
+ // one also able specify reference from other TDCs
+ // but one should enable CrossProcessing for trb3
+ // Here we set as reference channel 0 on tdc 1
+ // tdc->SetRefChannel(0, 0, 1);
+
+ // for old FPGA code one should have epoch for each hit, no longer necessary
+ // tdc->SetEveryEpoch(true);
+
+
+ // next parameters are about time calibration - there are two possibilities
+ // 1) automatic calibration after N hits in every enabled channel
+ // 2) generate calibration on base of provided data and than use it later statically for analysis
+
+ // disable calibration for channel #0
+ //tdc->DisableCalibrationFor(0);
+
+ // load static calibration at the beginning of the run
+ // tdc->LoadCalibration(Form("tdc2_%04x.cal", tdcmap[cnt]));
+
+ // calculate and write static calibration at the end of the run
+ // tdc->SetWriteCalibration(Form("tdc3_%04x.cal", tdcmap[cnt]));
+
+ // enable automatic calibration, specify required number of hits in each channel
+ tdc->SetAutoCalibration(100000);
+
+ // this will be required only when second analysis step will be introduced
+ // and one wants to select only hits around some trigger signal for that analysis
+
+ // method set window for all TDCs at the same time
+ //trb->SetTriggerWindow(-4e-7, -3e-7);
+
+#ifdef __GO4ANAMACRO__
+ int numx = 1;
+ int numy = 1;
+ while ((numx * numy) < tdc->NumChannels()) {
+ if (numx==numy) numx++; else numy++;
+ }
+
+ TGo4Picture** pic = new TGo4Picture*[tdc->GetNumHist()];
+ int* piccnt = new int[tdc->GetNumHist()];
+ for (int k=0;k<tdc->GetNumHist();k++) {
+ pic[k] = new TGo4Picture(Form("TDC%d_%s",tdcid, tdc->GetHistName(k)), Form("All %s", tdc->GetHistName(k)));
+ pic[k]->SetDivision(numy,numx);
+ piccnt[k] = 0;
+ }
+ for (int n=0;n<tdc->NumChannels();n++) {
+ int x = n % numx;
+ int y = n / numx;
+ for (int k=0;k<tdc->GetNumHist();k++) {
+ TObject* obj = (TObject*) tdc->GetHist(n, k);
+ if (obj) piccnt[k]++;
+ pic[k]->Pic(y,x)->AddObject(obj);
+ }
+ }
+ for (int k=0;k<tdc->GetNumHist();k++) {
+ if (piccnt[k] > 0) go4->AddPicture(pic[k]);
+ else delete pic[k];
+ }
+ delete[] pic;
+ delete[] piccnt;
+
+#endif
+
+ }
+
+
+ // This is a method to regularly invoke macro, where arbitrary action can be performed
+ // One could specify period in seconds or function will be called for every event processed
+
+ // new THookProc("my_hook();", 2.5);
+
+}
+
+
+
+// this is example of hook function
+// here one gets access to all tdc processors and obtains Mean and RMS
+// value on the first channel for each TDC and prints on the display
+
+void my_hook()
+{
+ hadaq::TrbProcessor* trb3 = base::ProcMgr::instance()->FindProc("TRB0");
+ if (trb3==0) return;
+
+ printf("Do extra work NUM %u\n", trb3->NumSubProc());
+
+ for (unsigned ntdc=0;ntdc<trb3->NumSubProc();ntdc++) {
+
+ hadaq::TdcProcessor* tdc = trb3->GetSubProc(ntdc);
+ if (tdc==0) continue;
+
+ TH1* hist = (TH1*) tdc->GetChannelRefHist(1);
+
+ printf(" TDC%u mean:%5.2f rms:%5.2f\n", tdc->GetBoardId(), hist->GetMean(), hist->GetRMS());
+
+ tdc->ClearChannelRefHist(1);
+ }
+
+}