@@ -47,10 +47,21 @@ class ReadoutEquipmentRORC : public ReadoutEquipment {
4747
4848 unsigned long long statsRdhCheckOk=0 ; // number of RDH structs which have passed check ok
4949 unsigned long long statsRdhCheckErr=0 ; // number of RDH structs which have not passed check
50+ unsigned long long statsNumberOfPages=0 ; // number of pages read out
51+ unsigned long long statsNumberOfTimeframes=0 ; // number of timeframes read out
52+
5053
5154 AliceO2::Common::Timer timeframeClock; // timeframe id should be increased at each clock cycle
52- int currentTimeframe=0 ; // id of current timeframe
55+ int currentTimeframe=0 ; // id of current timeframe
56+ bool usingSoftwareClock=false ; // if set, using internal software clock to generate timeframe id
57+
58+ const unsigned int LHCBunches=3564 ; // number of bunches in LHC
59+ const unsigned int LHCOrbitRate=11246 ; // LHC orbit rate, in Hz. 299792458 / 26659
60+ const uint32_t timeframePeriodOrbits=256 ; // timeframe interval duration in number of LHC orbits
5361
62+ uint32_t currentTimeframeHbOrbitBegin=0 ; // HbOrbit of beginning of timeframe
63+ uint32_t firstTimeframeHbOrbitBegin=0 ; // HbOrbit of beginning of first timeframe
64+
5465 size_t superPageSize=0 ; // usable size of a superpage
5566};
5667
@@ -202,9 +213,19 @@ ReadoutEquipmentRORC::ReadoutEquipmentRORC(ConfigFile &cfg, std::string name) :
202213 theLog.log (" ROC input queue size = %d pages" ,RocFifoSize);
203214 if (RocFifoSize==0 ) {RocFifoSize=1 ;}
204215
205- // reset timeframe clock
206- timeframeClock.reset (1000000 /50.0 ); // 50Hz rate
216+ // reset timeframe id
207217 currentTimeframe=0 ;
218+ if (!cfgRdhCheckEnabled) {
219+ usingSoftwareClock=true ; // if RDH disabled, use internal clock for TF id
220+ }
221+ if (usingSoftwareClock) {
222+ // reset timeframe clock
223+ double timeframeRate=LHCOrbitRate*1.0 /timeframePeriodOrbits; // timeframe rate, in Hz
224+ theLog.log (" Timeframe IDs generated by software, %.2lf Hz" ,timeframeRate);
225+ timeframeClock.reset (1000000 /timeframeRate);
226+ } else {
227+ theLog.log (" Timeframe IDs generated from RDH trigger counters" );
228+ }
208229
209230 }
210231 catch (const std::exception& e) {
@@ -222,7 +243,7 @@ ReadoutEquipmentRORC::~ReadoutEquipmentRORC() {
222243 }
223244
224245 if (cfgRdhCheckEnabled) {
225- theLog.log (" Equipment %s : RDH checks %llu ok, %llu errors" ,name.c_str (),statsRdhCheckOk,statsRdhCheckErr);
246+ theLog.log (" Equipment %s : %llu timeframes, %llu pages, RDH checks %llu ok, %llu errors" ,name.c_str (),statsNumberOfTimeframes,statsNumberOfPages ,statsRdhCheckOk,statsRdhCheckErr);
226247 }
227248}
228249
@@ -323,20 +344,22 @@ DataBlockContainerReference ReadoutEquipmentRORC::getNextBlock() {
323344 theLog.log (" make_shared<DataBlock> failed" );
324345 }
325346 if (d!=nullptr ) {
347+ statsNumberOfPages++;
348+
326349 d->getData ()->header .dataSize =superpage.getReceived ();
327350 d->getData ()->header .linkId =0 ; // TODO
328351
329352 channel->popSuperpage ();
330353 nextBlock=d;
331-
332- if (timeframeClock.isTimeout ()) {
333- currentTimeframe++;
334- timeframeClock.increment ();
335- }
336- d->getData ()->header .id =currentTimeframe;
337354
338355 // validate RDH structure, if configured to do so
339356 int linkId=-1 ;
357+ int hbOrbit=-1 ;
358+
359+ // checks to do:
360+ // - HB clock consistent in all RDHs
361+ // - increasing counters
362+
340363 if (cfgRdhCheckEnabled) {
341364 std::string errorDescription;
342365 size_t blockSize=d->getData ()->header .dataSize ;
@@ -352,6 +375,26 @@ DataBlockContainerReference ReadoutEquipmentRORC::getNextBlock() {
352375 }
353376 }
354377
378+ if (hbOrbit==-1 ) {
379+ hbOrbit=h.getHbOrbit ();
380+ if ((statsNumberOfPages==1 ) || ((uint32_t )hbOrbit>=currentTimeframeHbOrbitBegin+timeframePeriodOrbits)) {
381+ if (statsNumberOfPages==1 ) {
382+ firstTimeframeHbOrbitBegin=hbOrbit;
383+ }
384+ statsNumberOfTimeframes++;
385+ currentTimeframeHbOrbitBegin=hbOrbit-((hbOrbit-firstTimeframeHbOrbitBegin)%timeframePeriodOrbits); // keep it periodic and aligned to 1st timeframe
386+ int newTimeframe=1 +(currentTimeframeHbOrbitBegin-firstTimeframeHbOrbitBegin)/timeframePeriodOrbits;
387+ if (newTimeframe!=currentTimeframe+1 ) {
388+ printf (" Non-contiguous timeframe IDs %d ... %d\n " ,currentTimeframe,newTimeframe);
389+ }
390+ currentTimeframe=newTimeframe;
391+ // printf("Starting timeframe %d @ orbit %d (actual: %d)\n",currentTimeframe,(int)currentTimeframeHbOrbitBegin,(int)hbOrbit);
392+ } else {
393+ // printf("HB orbit %d\n",hbOrbit);
394+ }
395+
396+ }
397+
355398 // data format:
356399 // RDH v3 = https://docs.google.com/document/d/1otkSDYasqpVBDnxplBI7dWNxaZohctA-bvhyrzvtLoQ/edit?usp=sharing
357400 if (h.validateRdh (errorDescription)) {
@@ -383,7 +426,17 @@ DataBlockContainerReference ReadoutEquipmentRORC::getNextBlock() {
383426 if (linkId>=0 ) {
384427 d->getData ()->header .linkId =linkId;
385428 }
386-
429+
430+ if (usingSoftwareClock) {
431+ if (timeframeClock.isTimeout ()) {
432+ currentTimeframe++;
433+ statsNumberOfTimeframes++;
434+ timeframeClock.increment ();
435+ }
436+ }
437+
438+ // set timeframe id
439+ d->getData ()->header .id =currentTimeframe;
387440 }
388441 else {
389442 // no data block container... what to do???
0 commit comments