@@ -76,9 +76,13 @@ SBNDPTBDecoder::SBNDPTBDecoder(fhicl::ParameterSet const & p)
7676 produces<std::vector<raw::ptb::sbndptb> >(fOutputInstance );
7777}
7878
79+ int _run; int _subrun; int _event;
7980void SBNDPTBDecoder::produce (art::Event & evt)
8081{
81-
82+ _run = evt.id ().run ();
83+ _subrun = evt.id ().subRun ();
84+ _event = evt.id ().event ();
85+ std::cout << " Run: " << _run << " SubRun: " << _subrun << " Event: " << _event << std::endl;
8286
8387 // look first for container fragments and then non-container fragments
8488
@@ -117,6 +121,61 @@ void SBNDPTBDecoder::produce(art::Event & evt)
117121 evt.put (std::make_unique<std::vector<raw::ptb::sbndptb>>(std::move (sbndptbs)),fOutputInstance );
118122}
119123
124+
125+ void print_fragment_words (const artdaq::Fragment& frag, size_t wordNum, size_t bitsPerWord ) {
126+
127+ const __uint8_t * data_ptr = reinterpret_cast <const __uint8_t *>(frag.dataBegin ());
128+ size_t wordCount = frag.dataSizeBytes () / (bitsPerWord / 8 );
129+ for (size_t w = 0 ; w < wordCount; w++) {
130+ // Check if the current word index matches the specified word index
131+ if (w == wordNum) {
132+ // Print the bits for the specified n-bit word
133+ for (int i = (bitsPerWord-1 ); i >= 0 ; --i) {
134+ // Calculate the byte index and bit index
135+ size_t byteIndex = w * (bitsPerWord / 8 ) + (i / 8 );
136+ int bitIndex = (i % 8 ); // Get the correct bit position in the byte
137+ // Print the bit
138+ std::cout << static_cast <int >((data_ptr[byteIndex] >> bitIndex) & 1 );
139+ if (i % 8 == 0 ) {
140+ std::cout << " " ;
141+ }
142+ }
143+ std::cout << std::endl; // New line after printing the word
144+ }
145+ }
146+ }
147+
148+
149+ // Copied from Lines 1382-1406 from sbndaq-artdaq/sbndaq-artdaq/ArtModules/SBND/EventAna_module.cc
150+
151+ /* ******************************************
152+ * Note: Below for the Timestamp conversion,
153+ * The PTB TS is in UTC seconds since the Unix epoch in 50MHz clock ticks.
154+ * This means to recover seconds since the Unix epoch use: sec_since_epoch = TS / 50e6
155+ * and of course nanosec_since_epoch = (TS / 50e6) * 1e9 = TS * 20
156+ *
157+ * Note: The `CTBFragment` constructor grabs the chunk of memory the artDAQ fragment occupies.
158+ * Since we know a priori the number of PTB words (from the TCP header) and the size (128b for all words)
159+ * we can loop over the memory addresses, casting each 128b into the correct word type given by each word's `type`.
160+ *
161+ * There are 5 word types with the following bit arrangement:
162+ * Feeback = | 3b Word Type | 61b Payload | 64b Timestamp | (here Payload is split into code, source, payload1, payload2)
163+ * LLT, HLT = | 3b Word Type | 61b Payload | 64b Timestamp |
164+ * Channel Status = | 3b Word Type | 64b Payload | 61b Timestamp | (Larger Payload to fit all input channels)
165+ *
166+ * Word Type:
167+ * - 0x0 = Feedback/Error Word -> Errors from the firmware, should abort the run
168+ * - 0x1 = Low Level Trigger (LLT) -> Holds a record of any asserted LLTs
169+ * - 0x2 = High Level Trigger (HLT) -> Holds a record of any asserted HLTs
170+ * - 0x3 = Channel status -> Holds a record of any asserted inputs
171+ * - 0x7 = Timestamp Word -> No payload just a timestamp, these are periodic
172+ *
173+ * Note: Payload AND'd with mask the size of the expected number of bits just
174+ * to make sure we don't get any unexpected garbage bits since we aren't using
175+ * the full bits of the variable type e.g. uint64_t, unint16_t..
176+ **************************************/
177+
178+
120179void SBNDPTBDecoder::_process_PTB_AUX (const artdaq::Fragment& frag, ptbsv_t &sout)
121180{
122181 sbndaq::CTBFragment ctbfrag (frag); // somehow the name CTBFragment stuck
@@ -145,8 +204,24 @@ void SBNDPTBDecoder::_process_PTB_AUX(const artdaq::Fragment& frag, ptbsv_t &sou
145204 tstruct.timestamp = ctbfrag.Trigger (iword)->timestamp ;
146205 if (ctbfrag.Trigger (iword)->IsHLT ())
147206 {
207+
208+ if (*(frag.metadata <int >()) == 2 ){ // If data is taken with 192b PTB words
209+ tstruct.prev_timestamp = ctbfrag.PTBWord (iword)->prevTS ;
210+ tstruct.gate_counter = ctbfrag.Trigger (iword)->gate_counter ;
211+ }
212+ else if (*(frag.metadata <int >()) != 2 ){ // If data is taken with 128b PTB words
213+ tstruct.prev_timestamp = 0 ;
214+ tstruct.gate_counter = 0 ;
215+ }
216+
148217 ix = sout.HLTrigs .size ();
149218 sout.HLTrigs .push_back (tstruct);
219+
220+ // Make sure HLT words are printing correctly
221+ print_fragment_words (frag, iword, 192 );
222+ std::cout <<" Gate Counter: " << ctbfrag.Trigger (iword)->gate_counter << " | Trigger Payload: " << tstruct.trigger_word << " | Previous Timestamp: " << ctbfrag.PTBWord (iword)->prevTS *20 << std::endl;
223+
224+
150225 if (fDebugLevel > 0 )
151226 {
152227 std::cout << " SBNDPTBDecoder_module: found HLT: " << wt << " " << ix << std::endl;
0 commit comments