1 #include "artdaq-demo/Generators/ToyHardwareInterface/ToyHardwareInterface.hh"
2 #define TRACE_NAME "ToyHardwareInterface"
3 #include "artdaq/DAQdata/Globals.hh"
4 #include "artdaq-core-demo/Overlays/ToyFragment.hh"
5 #include "artdaq-core-demo/Overlays/FragmentType.hh"
7 #include "fhiclcpp/ParameterSet.h"
8 #include "cetlib_except/exception.h"
24 , nADCcounts_(ps.get<size_t>(
"nADCcounts", 40))
25 , maxADCcounts_(ps.get<size_t>(
"maxADCcounts", 50000000))
26 , change_after_N_seconds_(ps.get<size_t>(
"change_after_N_seconds",
27 std::numeric_limits<size_t>::max()))
28 , nADCcounts_after_N_seconds_(ps.get<int>(
"nADCcounts_after_N_seconds",
30 , exception_after_N_seconds_(ps.get<bool>(
"exception_after_N_seconds",
32 , exit_after_N_seconds_(ps.get<bool>(
"exit_after_N_seconds",
34 , abort_after_N_seconds_(ps.get<bool>(
"abort_after_N_seconds",
36 , fragment_type_(demo::toFragmentType(ps.get<std::string>(
"fragment_type")))
37 , maxADCvalue_(pow(2, NumADCBits()) - 1)
39 throttle_usecs_(ps.get<size_t>(
"throttle_usecs", 100000))
40 , usecs_between_sends_(ps.get<size_t>(
"usecs_between_sends", 0))
41 , distribution_type_(static_cast<
DistributionType>(ps.get<int>(
"distribution_type")))
42 , engine_(ps.get<int64_t>(
"random_seed", 314159))
43 , uniform_distn_(new std::uniform_int_distribution<
data_t>(0, maxADCvalue_))
44 , gaussian_distn_(new std::normal_distribution<double>(0.5 * maxADCvalue_, 0.1 * maxADCvalue_))
45 , start_time_(fake_time_)
47 , serial_number_((*uniform_distn_)(engine_))
49 #pragma GCC diagnostic push
50 #pragma GCC diagnostic ignored "-Wsign-compare"
58 if (nADCcounts_ > maxADCcounts_ ||
59 (nADCcounts_after_N_seconds_ >= 0 && nADCcounts_after_N_seconds_ > maxADCcounts_))
61 throw cet::exception(
"HardwareInterface") <<
"Either (or both) of \"nADCcounts\" and \"nADCcounts_after_N_seconds\"" <<
62 " is larger than the \"maxADCcounts\" setting (currently at " << maxADCcounts_ <<
")";
65 bool planned_disruption = nADCcounts_after_N_seconds_ != nADCcounts_ ||
66 exception_after_N_seconds_ ||
67 exit_after_N_seconds_ ||
68 abort_after_N_seconds_;
70 if (planned_disruption &&
71 change_after_N_seconds_ == std::numeric_limits<size_t>::max())
73 throw cet::exception(
"HardwareInterface") <<
"A FHiCL parameter designed to create a disruption has been set, so \"change_after_N_seconds\" should be set as well";
74 #pragma GCC diagnostic pop
93 start_time_ = fake_time_;
101 usleep(throttle_usecs_);
105 #pragma GCC diagnostic push
106 #pragma GCC diagnostic ignored "-Wsign-compare"
107 if (elapsed_secs_since_datataking_start < change_after_N_seconds_ || send_calls_ == 0)
109 #pragma GCC diagnostic pop
115 if (abort_after_N_seconds_)
119 else if (exit_after_N_seconds_)
123 else if (exception_after_N_seconds_)
125 throw cet::exception(
"HardwareInterface") <<
"This is an engineered exception designed for testing purposes";
127 else if (nADCcounts_after_N_seconds_ >= 0)
154 std::function<data_t()> generator;
157 switch (distribution_type_)
162 return static_cast<data_t>
163 ((*uniform_distn_)(engine_));
172 gen_seed =
static_cast<data_t>(std::round((*gaussian_distn_)(engine_)));
173 }
while (gen_seed > maxADCvalue_);
182 if (++gen_seed > maxADCvalue_) gen_seed = 0;
189 case DistributionType::uninit2:
193 throw cet::exception(
"HardwareInterface") <<
194 "Unknown distribution type specified";
199 std::generate_n(reinterpret_cast<data_t*>(reinterpret_cast<demo::ToyFragment::Header*>(buffer) + 1),
207 throw cet::exception(
"ToyHardwareInterface") <<
208 "Attempt to call FillBuffer when not sending data";
211 if (send_calls_ == 0)
212 { start_time_ = std::chrono::steady_clock::now();
213 TLOG(50) <<
"FillBuffer has set the start_time_";
216 if (usecs_between_sends_ != 0)
219 if (send_calls_ != 0)
222 #pragma GCC diagnostic push
223 #pragma GCC diagnostic ignored "-Wsign-compare"
226 long delta = (long)(usecs_between_sends_ * send_calls_) - usecs_since_start;
230 TLOG(15) <<
"FillBuffer send_calls=" << send_calls_ <<
" usecs_since_start=" << usecs_since_start <<
" delta=" << delta ;
232 #pragma GCC diagnostic pop
254 return static_cast<int>(fragment_type_) + 1000;
259 switch (fragment_type_)
261 case demo::FragmentType::TOY1:
264 case demo::FragmentType::TOY2:
268 throw cet::exception(
"ToyHardwareInterface")
269 <<
"Unknown board type "
280 return serial_number_;
int NumADCBits() const
Get the number of ADC bits used in generating data.
void StartDatataking()
"StartDatataking" is meant to mimic actions one would take when telling the hardware to start sending...
uint16_t data_t
The type used to represent ADC counts (which are 12 or 14 bits, for TOY1 or TOY2) ...
void StopDatataking()
Performs shutdown actions.
constexpr size_t GetElapsedTimeMicroseconds(std::chrono::steady_clock::time_point then, std::chrono::steady_clock::time_point now=std::chrono::steady_clock::now())
void FillBuffer(char *buffer, size_t *bytes_read)
Use configured generator to fill a buffer with data.
std::string fragmentTypeToString(FragmentType val)
DistributionType
Allow for the selection of output distribution.
void FreeReadoutBuffer(char *buffer)
Release the given buffer to the hardware.
A monotonically-increasing distribution.
constexpr double GetElapsedTime(std::chrono::steady_clock::time_point then, std::chrono::steady_clock::time_point now=std::chrono::steady_clock::now())
ToyHardwareInterface(fhicl::ParameterSet const &ps)
Construct and configure ToyHardwareInterface.
A use-after-free expliot distribution.
void AllocateReadoutBuffer(char **buffer)
Request a buffer from the hardware.
int SerialNumber() const
Gets the serial number of the simulated hardware.
int BoardType() const
Return the "board type" of the simulated hardware.