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);
249 B2DEBUG(200,
"Pack data for iCrate = " << iCrate <<
" nShapers = " << nShapers);
252 unsigned int eclCollectorHeader = (1 << nShapers) - 1;
254 buff[iFINESSE].push_back(eclCollectorHeader);
256 for (iShaper = 1; iShaper <= nShapers; iShaper++) {
258 nActiveDSPChannels =
shaperNHits[iCrate - 1][iShaper - 1];
259 B2DEBUG(200,
"iCrate = " << iCrate <<
" iShaper = " << iShaper <<
" nActiveDSPChannels = " << nActiveDSPChannels);
261 B2DEBUG(200,
"nActiveChannelsWithADCData = " << nActiveChannelsWithADCData);
265 unsigned int shaperDataLength = 4 + nActiveDSPChannels + nActiveChannelsWithADCData * ECL_ADC_SAMPLES_PER_CHANNEL;
267 unsigned int shaper_header_w0 = (0x10 << 16) + (shaperDataLength & 0xFFFF);
268 buff[iFINESSE].push_back(shaper_header_w0);
271 unsigned int shaper_header_w1 = (nActiveChannelsWithADCData & 0x1F) << 24;
272 shaper_header_w1 |= (ECL_ADC_SAMPLES_PER_CHANNEL & 0x7F) << 16;
273 shaper_header_w1 |= (nActiveDSPChannels & 0x1F) << 8;
274 shaper_header_w1 |= triggerPhase;
275 buff[iFINESSE].push_back(shaper_header_w1);
278 B2DEBUG(200,
"dspMask = " << std::hex << dspMask);
279 unsigned int shaper_header_w2 = (dspMask & 0xFFFF) << 16;
280 shaper_header_w2 |= (
m_EvtNum & 0xFFFF);
281 buff[iFINESSE].push_back(shaper_header_w2);
284 B2DEBUG(100,
"adcMask = " << std::hex << adcMask);
285 unsigned int shaper_header_w3 = (adcMask & 0xFFFF);
286 buff[iFINESSE].push_back(shaper_header_w3);
289 for (iChannel = 1; iChannel <= ECL_CHANNELS_IN_SHAPER; iChannel++) {
293 if (cid < 1)
continue;
296 if (i_digit < 0)
continue;
297 const int qua =
m_eclDigits[i_digit]->getQuality();
304 int chi_mantissa = 0, chi_exponent = 0;
305 int n_bits = ceil(log2(
double(chi)));
307 chi_exponent = ceil(
float(n_bits - 9) / 2.0);
308 chi_mantissa = chi >> chi_exponent * 2;
313 tim = (chi_exponent << 9) | chi_mantissa;
318 unsigned int hit_data = ((
unsigned int)(qua & 3) << 30) & 0xC0000000;
319 hit_data |= (tim & 0xFFF) << 18;
320 hit_data |= ((amp + 128) & 0x3FFFF);
321 buff[iFINESSE].push_back(hit_data);
323 B2DEBUG(100,
"cid = " << cid <<
" amp = " << amp <<
" tim = " << tim);
326 for (
int i = 0; i < ECL_CHANNELS_IN_SHAPER; i++)
adcBuffer_temp[i] = 0;
328 setBuffLength(
static_cast<int>(ECL_ADC_SAMPLES_PER_CHANNEL) *
static_cast<int>(ECL_CHANNELS_IN_SHAPER));
329 for (iChannel = 1; iChannel <= ECL_CHANNELS_IN_SHAPER; iChannel++) {
331 if (cid < 1)
continue;
333 if (i_wf < 0)
continue;
334 B2DEBUG(200,
"i_wf = " << i_wf);
338 unsigned int adc_data_base = 0;
339 unsigned int adc_data_diff_width = 0;
345 for (
unsigned int iSample = 0; iSample < ECL_ADC_SAMPLES_PER_CHANNEL; iSample++) {
350 B2DEBUG(250,
"ampMin = " << ampMin <<
" ampMax = " << ampMax);
352 adc_data_base = ampMin & 0x3FFFF;
354 adc_data_diff_width = (
unsigned int)(log2((
float)ampMax - (
float)ampMin)) + 1;
355 adc_data_diff_width &= 0x1F;
358 B2DEBUG(250,
"Width = " << adc_data_diff_width <<
" Base = " << adc_data_base);
360 for (
unsigned int iSample = 0; iSample < ECL_ADC_SAMPLES_PER_CHANNEL; iSample++) {
362 B2DEBUG(250,
"offset = " << adc_data_offset);
366 for (
unsigned int iSample = 0; iSample < ECL_ADC_SAMPLES_PER_CHANNEL; iSample++) {
375 for (
int i = 0; i <
m_bufPos; i++) {
386 for (
int i = 0; i < channels_count; i++) {
387 nwords[i] = buff[i].size();
389 buff[i][0] |= (nwords[i] - finesseHeaderNWords) * 4;
392 B2DEBUG(100,
"**** iEvt = " <<
m_EvtNum <<
" node= " << iCOPPERNode);
393 for (
int i = 0; i < channels_count; i++)
394 for (
unsigned int j = 0; j < buff[i].size(); j++) {
395 B2DEBUG(210,
">> " << std::hex << setfill(
'0') << setw(8) << buff[i][j]);
398 B2DEBUG(100,
"Call PackDetectorBuf");
400 int* pcie40_words[MAX_PCIE40_CH];
401 int pcie40_nwords[MAX_PCIE40_CH] = {};
403 for (
int i = 0; i < channels_count; i++) {
404 pcie40_nwords[i] = nwords[i];
405 pcie40_words[i] =
new int[ nwords[i] ];
406 for (
int j = 0; j < nwords[i]; j++) {
407 pcie40_words[i][j] = buff[i][j];
411 newRawECL->
PackDetectorBuf(pcie40_words, pcie40_nwords, rawcprpacker_info);
413 newRawECL->
PackDetectorBuf((
int*)buff[0].data(), nwords[0], (
int*)buff[1].data(), nwords[1],
414 nullptr, 0,
nullptr, 0, rawcprpacker_info);
441 if (!bitsToWrite)
return;
443 if (bitsToWrite >
sizeof(value) * 8) {
444 B2ERROR(
"Error compressing ADC samples: tying to write too long word");
445 throw Write_adc_samples_error();
450 B2ERROR(
"Error compressing ADC samples: unexpectedly reach end of buffer");
451 throw Write_adc_samples_error();
453 unsigned tmpval = (1 <<
m_bitPos) - 1;
462 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.