9#include <ecl/modules/eclPacker/eclPackerModule.h>
16#include <framework/logging/Logger.h>
19#include <ecl/dataobjects/ECLDigit.h>
20#include <ecl/dataobjects/ECLDsp.h>
23#include <rawdata/dataobjects/RawECL.h>
31ECLPackerModule::ECLPackerModule() :
35 m_EclWaveformSamples(),
47 setDescription(
"The module reads ECLDigits from the DataStore and writes ECLRaw data.");
48 addParam(
"InitFileName", m_eclMapperInitFileName,
"Initialization file",
string(
"/ecl/data/ecl_channels_map.txt"));
49 addParam(
"RawCOPPERsName", m_eclRawCOPPERsName,
"Name of the RawECL container",
string(
"RawECLs"));
50 addParam(
"CompressMode", m_compressMode,
"compress mode for ADC samples",
true);
51 addParam(
"AmpThreshold", m_ampThreshold,
"Amplitude threshold", -50);
52 addParam(
"PackWfRareFactor", m_WaveformRareFactor,
"Pack ADC samples for one of N events. No waveform is packed if 0", 100);
53 addParam(
"Pcie40Data", m_pcie40Data,
54 "If true: pack data as if sent from PCIe40 boards. Otherwise: pack data as if sent from COPPERs",
false);
57ECLPackerModule::~ECLPackerModule()
78 B2FATAL(
"ECL Packer: Can't initialize eclChannelMapper!");
92 B2DEBUG(50,
"EclPacker:: event called ");
96 B2DEBUG(50,
"EclPacker:: output data arrays created");
98 int nActiveChannelsWithADCData, nActiveDSPChannels;
99 int triggerPhase = 0, dspMask = 0;
103 int nEclWaveform =
m_eclDsps.getEntries();
105 for (
int i = 0; i < ECL_CRATES; i++) {
107 for (
int j = 0; j < ECL_BARREL_SHAPERS_IN_CRATE; j++) {
115 for (
int j = 0; j < ECL_TOTAL_CHANNELS; j++) {
120 B2DEBUG(100,
"EclPacker:: N_Digits = " << nEclDigits);
121 B2DEBUG(100,
"EclPacker:: N_Waveforms = " << nEclWaveform);
123 int iCOPPER, iFINESSE, iCrate, iShaper, iChannel, nShapers;
125 B2DEBUG(100,
"EclPacker:: Hits ======>> ");
126 int tot_dsp_hits = 0;
128 for (
int i_digit = 0; i_digit < nEclDigits; i_digit++) {
139 if (iCrate < 1 && iShaper < 1 && iChannel < 1) {
140 B2ERROR(
"Wrong crate/shaper/channel ids: " << iCrate <<
" " << iShaper <<
" " << iChannel <<
" for CID " << cid);
141 throw eclPacker_internal_error();
152 B2DEBUG(100,
"ECL Packer:: N Hits above threshold = " << tot_dsp_hits <<
" nWaveforms = " << nEclWaveform);
156 B2DEBUG(100,
"ECL Packer:: Pack waveform data for this event: " <<
m_EvtNum);
157 for (
int i_wf = 0; i_wf < nEclWaveform; i_wf++) {
165 for (
int i_digit = 0; i_digit < nEclDigits; i_digit++) {
185 rawcprpacker_info.
tt_ctime = 0x7123456;
186 rawcprpacker_info.
tt_utime = 0xF1234567;
190 B2DEBUG(100,
"EclPacker:: proceed COPPERs... ");
191 B2DEBUG(100,
"EclPacker:: ECL_COPPERS = " << ECL_COPPERS);
198 max_nodes = ECL_COPPERS;
200 const static int max_channels = MAX_PCIE40_CH;
203 for (iCOPPER = 1; iCOPPER <= max_nodes; iCOPPER++) {
204 std::vector <unsigned int> buff[max_channels];
207 channels_count = iCOPPER < 3 ? 18 : 16;
212 for (
int i = 0; i < max_channels; i++) buff[i].clear();
216 iCOPPERNode = BECL_ID + iCOPPER;
218 iCOPPERNode = (iCOPPER <= ECL_BARREL_COPPERS) ? BECL_ID + iCOPPER : EECL_ID + iCOPPER - ECL_BARREL_COPPERS;
221 bool skipNode =
true;
224 for (
int i = 0; i < channels_count; i++) {
226 B2DEBUG(200,
"iCOPPERNode = 0x" << std::hex << iCOPPERNode << std::dec <<
" nCrate = " << icr);
232 if (skipNode)
continue;
234 rawcprpacker_info.
node_id = iCOPPERNode;
238 int nwords[max_channels] = {0, 0};
239 const int finesseHeaderNWords = 3;
242 for (iFINESSE = 0; iFINESSE < channels_count; iFINESSE++) {
246 if (!nShapers) B2ERROR(
"Ecl packer:: Wrong shapers number " << nShapers);
248 B2DEBUG(200,
"Pack data for iCrate = " << iCrate <<
" nShapers = " << nShapers);
251 unsigned int eclCollectorHeader = (1 << nShapers) - 1;
253 buff[iFINESSE].push_back(eclCollectorHeader);
255 for (iShaper = 1; iShaper <= nShapers; iShaper++) {
257 nActiveDSPChannels =
shaperNHits[iCrate - 1][iShaper - 1];
258 B2DEBUG(200,
"iCrate = " << iCrate <<
" iShaper = " << iShaper <<
" nActiveDSPChannels = " << nActiveDSPChannels);
260 B2DEBUG(200,
"nActiveChannelsWithADCData = " << nActiveChannelsWithADCData);
264 unsigned int shaperDataLength = 4 + nActiveDSPChannels + nActiveChannelsWithADCData * ECL_ADC_SAMPLES_PER_CHANNEL;
266 unsigned int shaper_header_w0 = (0x10 << 16) + (shaperDataLength & 0xFFFF);
267 buff[iFINESSE].push_back(shaper_header_w0);
270 unsigned int shaper_header_w1 = (nActiveChannelsWithADCData & 0x1F) << 24;
271 shaper_header_w1 |= (ECL_ADC_SAMPLES_PER_CHANNEL & 0x7F) << 16;
272 shaper_header_w1 |= (nActiveDSPChannels & 0x1F) << 8;
273 shaper_header_w1 |= triggerPhase;
274 buff[iFINESSE].push_back(shaper_header_w1);
277 B2DEBUG(200,
"dspMask = " << std::hex << dspMask);
278 unsigned int shaper_header_w2 = (dspMask & 0xFFFF) << 16;
279 shaper_header_w2 |= (
m_EvtNum & 0xFFFF);
280 buff[iFINESSE].push_back(shaper_header_w2);
283 B2DEBUG(100,
"adcMask = " << std::hex << adcMask);
284 unsigned int shaper_header_w3 = (adcMask & 0xFFFF);
285 buff[iFINESSE].push_back(shaper_header_w3);
288 for (iChannel = 1; iChannel <= ECL_CHANNELS_IN_SHAPER; iChannel++) {
292 if (cid < 1)
continue;
295 if (i_digit < 0)
continue;
296 const int qua =
m_eclDigits[i_digit]->getQuality();
303 int chi_mantissa = 0, chi_exponent = 0;
304 int n_bits = ceil(log2(
double(chi)));
306 chi_exponent = ceil(
float(n_bits - 9) / 2.0);
307 chi_mantissa = chi >> chi_exponent * 2;
312 tim = (chi_exponent << 9) | chi_mantissa;
317 unsigned int hit_data = ((
unsigned int)(qua & 3) << 30) & 0xC0000000;
318 hit_data |= (tim & 0xFFF) << 18;
319 hit_data |= ((amp + 128) & 0x3FFFF);
320 buff[iFINESSE].push_back(hit_data);
322 B2DEBUG(100,
"cid = " << cid <<
" amp = " << amp <<
" tim = " << tim);
325 for (
int i = 0; i < ECL_CHANNELS_IN_SHAPER; i++)
adcBuffer_temp[i] = 0;
327 setBuffLength(
static_cast<int>(ECL_ADC_SAMPLES_PER_CHANNEL) *
static_cast<int>(ECL_CHANNELS_IN_SHAPER));
328 for (iChannel = 1; iChannel <= ECL_CHANNELS_IN_SHAPER; iChannel++) {
330 if (cid < 1)
continue;
332 if (i_wf < 0)
continue;
333 B2DEBUG(200,
"i_wf = " << i_wf);
337 unsigned int adc_data_base = 0;
338 unsigned int adc_data_diff_width = 0;
344 for (
unsigned int iSample = 0; iSample < ECL_ADC_SAMPLES_PER_CHANNEL; iSample++) {
349 B2DEBUG(250,
"ampMin = " << ampMin <<
" ampMax = " << ampMax);
351 adc_data_base = ampMin & 0x3FFFF;
353 adc_data_diff_width = (
unsigned int)(log2((
float)ampMax - (
float)ampMin)) + 1;
354 adc_data_diff_width &= 0x1F;
357 B2DEBUG(250,
"Width = " << adc_data_diff_width <<
" Base = " << adc_data_base);
359 for (
unsigned int iSample = 0; iSample < ECL_ADC_SAMPLES_PER_CHANNEL; iSample++) {
361 B2DEBUG(250,
"offset = " << adc_data_offset);
365 for (
unsigned int iSample = 0; iSample < ECL_ADC_SAMPLES_PER_CHANNEL; iSample++) {
374 for (
int i = 0; i <
m_bufPos; i++) {
385 for (
int i = 0; i < channels_count; i++) {
386 nwords[i] = buff[i].size();
388 buff[i][0] |= (nwords[i] - finesseHeaderNWords) * 4;
391 B2DEBUG(100,
"**** iEvt = " <<
m_EvtNum <<
" node= " << iCOPPERNode);
392 for (
int i = 0; i < channels_count; i++)
393 for (
unsigned int j = 0; j < buff[i].size(); j++) {
394 B2DEBUG(210,
">> " << std::hex << setfill(
'0') << setw(8) << buff[i][j]);
397 B2DEBUG(100,
"Call PackDetectorBuf");
399 int* pcie40_words[MAX_PCIE40_CH];
400 int pcie40_nwords[MAX_PCIE40_CH] = {};
402 for (
int i = 0; i < channels_count; i++) {
403 pcie40_nwords[i] = nwords[i];
404 pcie40_words[i] =
new int[ nwords[i] ];
405 for (
int j = 0; j < nwords[i]; j++) {
406 pcie40_words[i][j] = buff[i][j];
410 newRawECL->
PackDetectorBuf(pcie40_words, pcie40_nwords, rawcprpacker_info);
412 newRawECL->
PackDetectorBuf((
int*)buff[0].data(), nwords[0], (
int*)buff[1].data(), nwords[1],
413 nullptr, 0,
nullptr, 0, rawcprpacker_info);
440 if (!bitsToWrite)
return;
442 if (bitsToWrite >
sizeof(value) * 8) {
443 B2ERROR(
"Error compressing ADC samples: tying to write too long word");
444 throw Write_adc_samples_error();
449 B2ERROR(
"Error compressing ADC samples: unexpectedly reach end of buffer");
450 throw Write_adc_samples_error();
452 unsigned tmpval = (1 <<
m_bitPos) - 1;
461 unsigned tmpval = (1 <<
m_bitPos) - 1;
In the store you can park objects that have to be accessed by various modules.
StoreArray< ECLDsp > m_eclDsps
ECLDSP dataStore object.
int m_ampThreshold
DSP amplitude threshold.
int iEclDigIndices[ECL::ECL_TOTAL_CHANNELS]
indexes of related eclDigits
int shaperNHits[ECL::ECL_CRATES][ECL::ECL_BARREL_SHAPERS_IN_CRATE]
Number of hits per shaper.
int shaperMaskArray[ECL::ECL_CRATES][ECL::ECL_BARREL_SHAPERS_IN_CRATE]
triggered shapers
int m_EvtNum
Event number.
ECL::ECLChannelMapper m_eclMapper
channel mapper
int iEclWfIndices[ECL::ECL_TOTAL_CHANNELS]
indexes of related waveforms
int shaperADCMaskArray[ECL::ECL_CRATES][ECL::ECL_BARREL_SHAPERS_IN_CRATE]
shapers with ADC data
virtual void initialize() override
initialize
int m_bufPos
position in the data array
int m_EclWaveformSamples[ECL_ADC_SAMPLES_PER_CHANNEL]
array of ADC samples
virtual void event() override
event
int shaperNWaveform[ECL::ECL_CRATES][ECL::ECL_BARREL_SHAPERS_IN_CRATE]
Number of waveforms per shaper.
int m_WaveformRareFactor
the rate of writing of the ADC samples
virtual void endRun() override
endRun
int m_bitPos
bit position for bit-by-bit data read
virtual void terminate() override
terminate
StoreArray< ECLDigit > m_eclDigits
ECLDigit dataStore object.
StoreObjPtr< EventMetaData > m_eventMetaData
store objptr for EventMetaData
bool m_pcie40Data
true-pack data in PCIe40 format, false-pack data in COPPER format
void setBuffLength(int bufLength)
set buffer length
virtual void beginRun() override
beginRun
StoreArray< RawECL > m_eclRawCOPPERs
Output data
unsigned int adcBuffer_temp[static_cast< int >(ECL::ECL_CHANNELS_IN_SHAPER) *static_cast< int >(ECL_ADC_SAMPLES_PER_CHANNEL)]
temporary buffer to store ADC data
bool m_compressMode
enable/disable compression of waveform data
int m_bufLength
length data
int collectorMaskArray[ECL::ECL_CRATES]
array of triggered collectors
void writeNBits(unsigned int *buff, unsigned int value, unsigned int bitsToWrite)
write N bits to the collector buffer
void resetBuffPosition()
reset current position in the buffer
std::string m_eclRawCOPPERsName
name of output collection for RawCOPPER
bool initFromDB()
Initialize channel mapper from the conditions database.
int getNShapersInCrate(int iCrate)
Get number of ShaperDSP modules in the given VME crate number.
int getCellId(int iCrate, int iShaper, int iChannel)
Get CellId by given crate number, shaper position in the crate and DSP channel number in the shaper.
int getShaperChannel(int cellID)
Get number of DSP channel in the shaper by given number of CellId.
int getShaperPosition(int cellID)
Get position of the shaper in the crate by given CellId.
int getCrateID(int iCOPPERNode, int iFINESSE, bool pcie40=false)
Get crate number by given COPPER node number and FINESSE number.
struct to contain header information used by RawCOPPERFormat::Packer()
unsigned int b2l_ctime
32bit unitx time at trigger timing distributed by FTSW. For details, see Nakao-san's belle2link user ...
unsigned int eve_num
Run # and subrun # ( 22bit )
unsigned int tt_ctime
Node ID (32bit)
unsigned int tt_utime
27bit clock ticks at trigger timing distributed by FTSW. For details, see Nakao-san's belle2link user...
unsigned int node_id
Event Number (32bit)
unsigned int run_subrun_num
Experiment number (10bit)
unsigned int exp_num
Experiment number (10bit)
void PackDetectorBuf(int *detector_buf_1st, int nwords_1st, int *detector_buf_2nd, int nwords_2nd, int *detector_buf_3rd, int nwords_3rd, int *detector_buf_4th, int nwords_4th, RawCOPPERPackerInfo rawcprpacker_info)
Packer for RawCOPPER class Pack data (format ver.
The Raw ECL class Class for RawCOPPER class data taken by ECL Currently, this class is almost same as...
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.