McStas Readout Master 0.8.0
Loading...
Searching...
No Matches
Sender.h
Go to the documentation of this file.
1// Copyright (C) 2022 European Spallation Source, ERIC. See LICENSE file
2//===----------------------------------------------------------------------===//
7//===----------------------------------------------------------------------===//
8#pragma once
9
10#include "cluon-complete.hpp"
11
12#include <atomic>
13#include <cstdint>
14#include <string>
15#include <utility>
16#include <optional>
17#include <random>
18
19#include "Structs.h"
20#include "Readout.h"
21#include "SenderConfigs.h"
22#include "enums.h"
23#include "hdf_interface.h"
24#include "version.hpp"
25#include "efu_time.h"
26
44class RL_API Sender {
45public:
46 Sender(
47 std::string IpAddress, const int UDPPort, const int TCPPort, const DetectorType detector_type, const ReadoutType readout_type, const pulse_grid grid
48 ): detector_type(detector_type),
49 readout_type(readout_type),
50 ipaddr(std::move(IpAddress)),
51 port(UDPPort),
52 tcp_port(TCPPort),
53 grid(grid),
54 period(grid.period()),
55 sender{ipaddr, static_cast<uint16_t>(UDPPort)}
56 {
57 // the latest pulse already past, as for a source that has been running all along
58 set_pulse(grid.at_or_before(efu_time::now_nanoseconds()));
59 newPacket();
60 }
61
62 Sender(
63 std::string IpAddress, const int UDPPort, const int TCPPort, const DetectorType detector_type, const ReadoutType readout_type, const efu_time p = efu_time(1)
64 ): Sender(std::move(IpAddress), UDPPort, TCPPort, detector_type, readout_type, pulse_grid::from_period(p)) {}
65
66 explicit Sender(const SenderConfig & config, const pulse_grid grid)
67 : Sender(config.ip_address, config.udp_port, config.tcp_port, config.detector_type, config.readout_type, grid) {}
68
69 explicit Sender(const SenderConfig & config, const efu_time p = efu_time(1))
70 : Sender(config, pulse_grid::from_period(p)) {}
71
72 ~Sender() {
73 // ensure any buffered readouts are sent before the object is destroyed
74 if (DataSize > static_cast<int>(sizeof(struct PacketHeaderV0))) {
75 send();
76 }
77 report_long_tof();
78 }
79
83 void addReadout(uint8_t Ring, uint8_t FEN, double tof, double weight, const void * data);
85 void addReadout(uint8_t Ring, uint8_t FEN, efu_time t, const void * data);
86 // Specializations for handled data types
87 void addReadout(uint8_t Ring, uint8_t FEN, efu_time t, const CAEN_readout_t * data);
88 void addReadout(uint8_t Ring, uint8_t FEN, efu_time t, const CDT_readout_t * data);
89 void addReadout(uint8_t Ring, uint8_t FEN, efu_time t, const VMM3_readout_t * data);
90 void addReadout(uint8_t Ring, uint8_t FEN, efu_time t, const BM0_readout_t * data);
91 void addReadout(uint8_t Ring, uint8_t FEN, efu_time t, const BM2_readout_t * data);
92 void addReadout(uint8_t Ring, uint8_t FEN, efu_time t, const BMI_readout_t * data);
93
94
97 int send();
98
100 void setPulseTime(uint32_t PHI, uint32_t PLO, uint32_t PPHI, uint32_t PPLO);
101
109 void begin_pulse_at(uint64_t at);
111 [[nodiscard]] uint64_t next_pulse() const;
118 void flush();
122 void hold_pulse(const bool hold) { hold_pulse_ = hold; }
123
128 void fold_tof(const bool fold) { fold_tof_ = fold; }
130 [[nodiscard]] uint64_t long_tof_count() const { return long_tof_; }
131
132 // Query the current pulse and previous pulse times
133 [[nodiscard]] std::pair<uint32_t, uint32_t> lastPulseTime() const;
135 [[nodiscard]] uint64_t lastPulseNanoseconds() const { return pulse_ns; }
136 [[nodiscard]] std::pair<uint32_t, uint32_t> prevPulseTime() const;
137 [[nodiscard]] std::pair<uint32_t, uint32_t> lastEventTime() const;
138
140 void newPacket();
141
143 int command_shutdown() const;
144
146 int verbose(const Verbosity v){
147 switch (v) {
148 case Verbosity::details: verbosity=3; break;
149 case Verbosity::info: verbosity=2; break;
150 case Verbosity::warnings: verbosity=1; break;
151 case Verbosity::errors: verbosity=0; break;
152 case Verbosity::silent: verbosity=-1; break;
153 default: verbosity=0;
154 }
155 return verbosity;
156 }
157 int verbose(const int v){verbosity = v; return verbosity;}
158private:
159
160 void check_size_and_send();
161
164 void maybe_advance_pulse();
165
167 void set_pulse(uint64_t ns);
168
169 // Packet header
170 uint32_t phi{0}; // pulse and prev pulse high and low
171 uint32_t plo{0};
172 uint32_t pphi{0};
173 uint32_t pplo{0};
174
175 uint32_t lasthi{0};
176 uint32_t lastlo{0};
177
178 int SeqNum{0};
179 int OutputQueue{0};
180 DetectorType detector_type;
181 ReadoutType readout_type;
182
183 // TX Buffer
184 // PacketHeaderV0 *hp{};
185 char buffer[9000]{};
186 const int MaxDataSize{8950};
187 int DataSize{0};
188 // IP and port number
189 std::string ipaddr;
190 int port{9000};
191 int tcp_port{8888};
192 int verbosity{0};
193 bool fold_tof_{false};
194 bool hold_pulse_{false};
195 std::atomic<uint64_t> long_tof_{0};
196 void report_long_tof() const;
197
198 pulse_grid grid;
199 efu_time period, time;
200 uint64_t pulse_ns{0};
201 cluon::UDPSender sender;
202
203 std::mutex time_mutex, send_mutex;
204};
Umbrella header for the C API used by the McStas components.
ESS and Bifrost readout data structures.
Buffers ESS readout records and transmits them as UDP packets to one EFU.
Definition Sender.h:44
void announce_pulse()
Send the current pulse's header with no readouts, so the EFU sees the pulse even when nothing is dete...
uint64_t lastPulseNanoseconds() const
The current pulse exactly, in nanoseconds since the UNIX epoch: a pulse_grid tick.
Definition Sender.h:135
void hold_pulse(const bool hold)
Keep the pulse begun by begin_pulse()/begin_pulse_at() however long sending takes,...
Definition Sender.h:122
void newPacket()
Initialize a new packet with no readouts.
uint64_t long_tof_count() const
How many readouts so far had a time-of-flight of at least one pulse period.
Definition Sender.h:130
void addReadout(uint8_t Ring, uint8_t FEN, efu_time t, const void *data)
Add a single readout with an explicit event time.
void begin_pulse_at(uint64_t at)
begin_pulse(), at the grid tick at (rounded up onto the grid), so that several Senders can begin one ...
void flush()
Send whatever is buffered for the current pulse now.
int command_shutdown() const
Tell the remote EFU to shut down via its TCP command port.
int send()
Transmit the current data buffer; the caller is responsible for starting a new packet (newPacket()) b...
uint64_t next_pulse() const
The tick begin_pulse() would begin: the first after now and after the current pulse.
void setPulseTime(uint32_t PHI, uint32_t PLO, uint32_t PPHI, uint32_t PPLO)
Update the pulse and previous pulse times (high/low pairs).
void begin_pulse()
Start a new pulse: flush any buffered readouts, wait until the next pulse-grid tick has passed on the...
int verbose(const Verbosity v)
Set verbosity via enum.
Definition Sender.h:146
void fold_tof(const bool fold)
Choose whether add-by-time-of-flight readouts are stamped at pulse + (tof % period) — attributing eac...
Definition Sender.h:128
void addReadout(uint8_t Ring, uint8_t FEN, double tof, double weight, const void *data)
Add one readout with its event time set to the current pulse time plus tof; the weight is ignored (st...
ESS EFU two-integer timestamp: whole seconds since the UNIX epoch plus ticks of the 88....
Definition efu_time.h:19
static uint64_t now_nanoseconds()
The system clock, in nanoseconds since the UNIX epoch.
Definition efu_time.h:132
The source's pulses: pulse k is at k periods after the UNIX epoch.
Definition efu_time.h:177
static pulse_grid from_period(const efu_time &period)
For a period given as a time: to the nearest nanosecond. efu_time(double) truncates to a whole tick,...
Definition efu_time.h:190
uint64_t at_or_before(const uint64_t ns) const
The latest pulse at or before ns.
Definition efu_time.h:197
One Event Formation Unit endpoint for a (detector, readout) pair.
uint16_t tcp_port
command port
uint16_t udp_port
event-packet port