#include #include #include #include #include #include namespace RAT { clock::clock() { } clock::~clock() { } void clock::SetRolloverInterval() { //calculate number of rollovers (period / ns) fNsecsRollover = fPeriod*pow(2.0,int(fNbits)); fRolloverDays = (UInt_t) ((fNsecsRollover*1.E-9)/86400.0); fRolloverSecs = (int)((fNsecsRollover*1.E-9) - (fRolloverDays*86400)); fRolloverNsecs = fNsecsRollover - (fRolloverSecs + fRolloverDays*86400)*1.E9; } void clock::SetFrequency(double freq) { fFrequency = freq; fPeriod = 1./(1.E-9*fFrequency); } double clock::GetNextTickTime(double time) { //time is time referenced to start of current event //to get next tick, we will need to reference this to //the SNO+ global time zero // EventTime *TimeNow = new EventTime; TimeNow->SetStart(); TimeNow->IncrementUT(time); double delta_t_nsecs = (double) TimeNow->GetFullUTNsecs(); ///The 0.0001 factor below nudges us so that we're always either bang //on or one rollover too far, a la Nick West. We then correct this //later. // UInt_t numRollover = (int)(delta_t_nsecs/fNsecsRollover + 0.0001); //Create an EventTime for the latest rollover EventTime *TimeRoll = new EventTime; ULong64_t l_nsec; int i_sec,i_day; double d_nsec; l_nsec=(ULong64_t)(numRollover*fRolloverNsecs); d_nsec=l_nsec%1000000000; TimeRoll->SetUTNsecs(d_nsec); i_sec=l_nsec/1000000000; //nanoseconds integer divide by 1.E9 i_sec = i_sec+numRollover*fRolloverSecs; i_day = i_sec/86400; i_sec = i_sec%86400; TimeRoll->SetUTSecs(i_sec); i_day = i_day + numRollover*fRolloverDays; TimeRoll->SetUTDays(i_day); // Now do fine tuning. If the rollover date is greater than the given // date we did done one too many rollovers, so step back one. // TimeOrder returns true if the calling object occurred before the argument // If TimeNow was before TimeRoll, we need to step back bool rollback = TimeNow->TimeOrder(TimeRoll); if(rollback){ TimeRoll->IncrementUT(-fNsecsRollover); } EventTime DeltaTimeRoll; DeltaTimeRoll = TimeNow->CompareUT(TimeRoll); // days,s are exactly divisible by clock period double extraTicks = (DeltaTimeRoll.GetUTNsecs()) / fPeriod; double timeToNextTick = (1.0-(extraTicks-(UInt_t) extraTicks))*fPeriod; double nextTime = time+timeToNextTick; ULong64_t nTicksDay = (ULong64_t)((double)(DeltaTimeRoll.GetUTDays())*86400.*1.e9 / fPeriod); ULong64_t nTicksSec = (ULong64_t)((double)(DeltaTimeRoll.GetUTSecs())*1.e9 / fPeriod); ULong64_t nTicksNse = (ULong64_t)extraTicks; fCount = nTicksDay + nTicksSec + nTicksNse; delete TimeNow; delete TimeRoll; return nextTime; } ULong64_t clock::GetCount(EventTime time) { ULong64_t nTicksDay = (ULong64_t)((double)(time.GetUTDays())*86400.*1.e9 / fPeriod); ULong64_t nTicksSec = (ULong64_t)((double)(time.GetUTSecs())*1.e9 / fPeriod); ULong64_t nTicksNse = (ULong64_t)(time.GetUTNsecs()/fPeriod); fCount = nTicksDay + nTicksSec + nTicksNse; unsigned long bDiv = 1; bDiv = bDiv << fNbits; fCount %= bDiv; return fCount; } EventTime clock::GetUTime() { // fCount = number of ticks // fPeriod*fCount = number of (int) ns ULong64_t Total = fCount * ((ULong64_t)fPeriod); ULong64_t NNsec = (Total)%((ULong64_t)1e9); ULong64_t NSecs = Total/((ULong64_t)1e9); ULong64_t NDays = NSecs/86400; NSecs = NSecs - (86400*NDays); UInt_t ndays = (UInt_t)NDays; UInt_t nsecs = (UInt_t)NSecs; Double_t nns = (double)NNsec; if(Total != (ULong64_t)NNsec + (ULong64_t)(1e9*NSecs) + (ULong64_t)(86400*1e9*NDays)){ //printf("\033[31m Total of %55u != %32u ns, %32u s, %32u d \033[m\n",Total, NNsec, NSecs, NDays); } EventTime thisTime; //thisTime.SetUT(NDays, NSecs, (double)NNsec); thisTime.SetUT(ndays, nsecs, nns); return thisTime; } } // namespace RAT