19UHAL_REGISTER_DERIVED_NODE(MasterNode)
35 std::stringstream status;
37 status << getNode<TimestampGeneratorNode>(
"tstamp").get_status();
40 status << getNode<MasterGlobalNode>(
"global").get_status();
43 status << getNode<FLCmdGeneratorNode>(
"scmd_gen").get_cmd_counters_table();
46 getNode(
"cmd_ctrs.addr").write(0x0);
47 auto counters = getNode(
"cmd_ctrs.data").readBlock(0xff);
48 getClient().dispatch();
50 std::vector<uint32_t> non_zero_counters;
51 std::vector<std::string> counter_labels;
53 for (uint i=0; i < counters.size(); ++i)
55 auto counter = counters.at(i);
59 non_zero_counters.push_back(counter);
63 std::vector<std::vector<uint32_t>> counters_container = { non_zero_counters };
65 status <<
format_counters_table(counters_container, {
"Sent cmd counters" },
"Master cmd counters (>0)", counter_labels);
79 std::stringstream status;
80 auto raw_timestamp = getNode<TimestampGeneratorNode>(
"tstamp").read_raw_timestamp();
81 status <<
"Timestamp: 0x" << std::hex <<
tstamp2int(raw_timestamp) << std::endl << std::endl;
85 TLOG() << status.str();
94 std::stringstream status;
95 auto raw_timestamp = getNode<TimestampGeneratorNode>(
"tstamp").read_raw_timestamp();
96 status <<
"Timestamp: 0x" << std::hex <<
tstamp2int(raw_timestamp) <<
" -> " <<
format_timestamp(raw_timestamp, clock_frequency_hz) << std::endl
98 status << get_status_tables();
101 TLOG() << status.str();
110 uint32_t sequence = 0xab;
111 uint32_t address_mode = 1;
113 std::vector<uint32_t> tx_packet = {
address & 0xff,
119 (address_mode << 7UL) | 0x1,
122 tx_packet.back() = tx_packet.back() | (0x1 << 8UL);
124 auto result = transmit_async_packet(tx_packet, -1);
132 auto global = getNode<MasterGlobalNode>(
"global");
133 global.enable_upstream_endpoint();
141 uint32_t number_of_commands)
const
143 for (uint32_t i = 0; i < number_of_commands; i++) {
144 getNode<FLCmdGeneratorNode>(
"scmd_gen").send_fl_cmd(command, channel);
146 auto ts_l = getNode(
"cmd_log.tstamp_l").read();
147 auto ts_h = getNode(
"cmd_log.tstamp_h").read();
148 auto sent_cmd = getNode(
"cmd_log.cmd").read();
149 getClient().dispatch();
151 if (sent_cmd.value() != command)
153 TLOG() <<
"cmd in sent log: 0x" << std::hex << command <<
", does not match requested 0x: " << sent_cmd.value();
156 uint64_t timestamp = (uint64_t)ts_h.value() << 32 | ts_l.value();
158 <<
format_reg_value(channel) <<
" @time " << std::hex << std::showbase << timestamp;
168 auto global = getNode<MasterGlobalNode>(
"global");
169 auto echo = getNode<EchoMonitorNode>(
"echo_mon");
177 switch_endpoint_sfp(
address,
true);
183 global.enable_upstream_endpoint();
185 catch (
const timing::ReceiverNotReady& e)
188 switch_endpoint_sfp(
address,
false);
194 uint32_t endpoint_rtt = echo.send_echo_and_measure_delay();
197 switch_endpoint_sfp(
address,
false);
206 uint32_t coarse_delay,
210 bool control_sfp)
const
213 auto global = getNode<MasterGlobalNode>(
"global");
214 auto echo = getNode<EchoMonitorNode>(
"echo_mon");
229 global.enable_upstream_endpoint();
231 catch (
const timing::ReceiverNotReady& e)
239 uint64_t endpoint_rtt = echo.send_echo_and_measure_delay();
243 uint32_t sequence = 0xab;
244 uint32_t address_mode = 1;
246 std::vector<uint32_t> tx_packet = {
address & 0xff,
252 (address_mode << 7UL) | 0x1,
253 ((fine_delay & 0xf) << 4UL) | (coarse_delay & 0xf),
257 (address_mode << 7UL) | 0x1,
258 (fine_delay >> 4UL) & 0xff,
262 (address_mode << 7UL) | 0x1,
267 (address_mode << 7UL) | 0x1,
271 tx_packet.back() = tx_packet.back() | (0x1 << 8UL);
278 global.enable_upstream_endpoint();
280 catch (
const timing::ReceiverNotReady& e)
289 uint64_t endpoint_rtt = echo.send_echo_and_measure_delay();
302 set_timestamp(source);
304 enable_timestamp_broadcast();
305 TLOG() <<
"Timestamp broadcast enabled";
313 return getNode<TimestampGeneratorNode>(
"tstamp").read_timestamp();
321 getNode<TimestampGeneratorNode>(
"tstamp").set_timestamp(source);
333 getClient().dispatch();
336 mon_data.
ts_valid = state.at(
"ts_valid").value();
337 mon_data.
ts_tx_err = state.at(
"ts_tx_err").value();
338 mon_data.
tx_err = state.at(
"tx_err").value();
339 mon_data.
ctrs_rdy = state.at(
"ctrs_rdy").value();
370 auto global = getNode<MasterGlobalNode>(
"global");
371 global.reset_command_counters();
384 for (
auto t : packet)
387 getNode(
"acmd_buf.txbuf").writeBlock(packet);
388 getClient().dispatch();
393 std::vector<uint32_t> empty_vector;
397 uhal::ValWord<uint32_t> buffer_ready;
398 uhal::ValWord<uint32_t> buffer_timeout;
401 auto start = std::chrono::high_resolution_clock::now();
406 buffer_ready = getNode(
"acmd_buf.stat.ready").read();
407 buffer_timeout = getNode(
"acmd_buf.stat.timeout").read();
408 getClient().dispatch();
410 TLOG_DEBUG(10) <<
"async buffer ready: 0x" << buffer_ready.value() <<
", timeout: " << buffer_timeout.value();
413 throw VLCommandReplyTimeout(
ERS_HERE);
418 auto now = std::chrono::high_resolution_clock::now();
419 auto us_since_start = std::chrono::duration_cast<std::chrono::microseconds>(
now - start);
421 if (us_since_start.count() > timeout)
422 throw VLCommandReplyBufferFlagTimeout(
ERS_HERE, timeout);
424 std::this_thread::sleep_for(std::chrono::microseconds(50));
427 auto rx_packet = getNode(
"acmd_buf.rxbuf").readBlock(0x20);
428 getClient().dispatch();
430 if (rx_packet.at(0) != 0xff || rx_packet.at(1) != 0xff || rx_packet.at(2) != packet.at(2))
432 ers::warning(InvalidVLCommandReplyPacket(
ERS_HERE, rx_packet.at(0), rx_packet.at(1), rx_packet.at(2)));
436 for (
auto r : rx_packet)
439 return rx_packet.value();
447 auto data_length = data.size();
448 if (data_length > 0x3f || data_length == 0)
450 TLOG() <<
"invalid data length";
454 uint32_t sequence = 0xab;
456 std::vector<uint32_t> tx_packet = {
static_cast<uint32_t
>(endpoint_address & 0xff),
457 static_cast<uint32_t
>(endpoint_address >> 8UL),
460 static_cast<uint32_t
>((0x1 << 7UL) | reg_address),
461 static_cast<uint32_t
>((address_mode << 7UL) | (0x3f & data_length))
463 tx_packet.insert(tx_packet.end(), data.begin(), data.end());
464 tx_packet.back() = tx_packet.back() | (0x1 << 8UL);
474 if (data_length > 0x3f || data_length == 0)
476 TLOG() <<
"invalid data length";
481 uint32_t sequence = 0xab;
482 std::vector<uint32_t> tx_packet = {
static_cast<uint32_t
>(endpoint_address & 0xff),
483 static_cast<uint32_t
>(endpoint_address >> 8UL),
487 static_cast<uint32_t
>((0x1 << 8UL) | (address_mode << 7UL) | (0x3f & data_length))
493 std::vector<uint32_t> result_data (result.begin()+3, result.begin()+3+data_length);
496 result_data.back() = result_data.back() & 0xff;
505 getNode(
"global.csr.ctrl.ts_en").write(0x0);
506 getClient().dispatch();
513 getNode(
"global.csr.ctrl.ts_en").write(0x1);
514 getClient().dispatch();
523 auto global = getNode<MasterGlobalNode>(
"global");
524 auto echo = getNode<EchoMonitorNode>(
"echo_mon");
527 endpoint_result.
address = endpoint_address;
540 global.enable_upstream_endpoint();
542 catch (
const timing::ReceiverNotReady& e)
548 return endpoint_result;
551 endpoint_result.
alive =
true;
556 TLOG_DEBUG(5) <<
"Endpoint at address " << endpoint_address <<
" state: 0x" << std::hex << ept_state;
557 endpoint_result.
state = ept_state;
559 if (ept_state == 0x6)
561 TLOG_DEBUG(5) <<
"Endpoint at address " << endpoint_address <<
", applying delays of: " << 0x0;
562 ers::info(MonitoredEndpointDelaySet(
ERS_HERE, 0x0, endpoint_address, ept_state));
567 auto ept_state_after_delays =
read_endpoint_data(endpoint_address, 0x71, 0x1, 0x1).at(0) & 0xf;
568 TLOG_DEBUG(5) <<
"Endpoint at address " << endpoint_address <<
", state after delays apply: " << ept_state_after_delays;
574 else if (ept_state == 0x7 || ept_state == 0x8)
576 TLOG_DEBUG(5) <<
"Endpoint at address " << endpoint_address <<
", delays not needed";
588 return endpoint_result;
Base class for timing IO nodes.
Class for PD-II/DUNE master timing nodes.
std::string get_status_tables() const
Get the status tables.
void set_timestamp(TimestampSource source) const override
Set the timestamp to current time.
std::string get_status(bool print_out=false) const override
Print the status of the timing node.
std::string get_status_with_date(uint32_t clock_frequency_hz, bool print_out=false) const
Print the status of the timing node.
std::vector< uint32_t > transmit_async_packet(const std::vector< uint32_t > &packet, int timeout=500) const
Send an async packet.
void enable_timestamp_broadcast() const
Enable timestamp sending.
uint64_t read_timestamp() const override
Read the current timestamp word.
void apply_endpoint_delay(uint32_t address, uint32_t coarse_delay, uint32_t fine_delay, uint32_t phase_delay, bool measure_rtt=false, bool control_sfp=true) const override
Apply delay to endpoint.
std::vector< uint32_t > read_endpoint_data(uint16_t endpoint_address, uint8_t reg_address, uint8_t data_length, bool address_mode) const
Read some data from endpoint registers.
uint32_t measure_endpoint_rtt(uint32_t address, bool control_sfp=true) const override
Measure the endpoint round trip time.
void switch_endpoint_sfp(uint32_t address, bool turn_on) const override
Control the tx line of endpoint sfp.
void disable_timestamp_broadcast() const
Disable timestamp sending.
timingfirmware::EndpointCheckResult scan_endpoint(uint16_t endpoint_address, bool control_sfp) const override
Scan endpoint.
void enable_upstream_endpoint() const override
Enable RTT endpoint.
void sync_timestamp(TimestampSource source) const override
Set timestamp to current machine time.
void configure_endpoint_command_decoder(uint16_t endpoint_address, uint8_t slot, uint8_t command) const
Configure endpoint command decoder.
void get_info(timingfirmwareinfo::MasterMonitorData &mon_data) const
Fill the PD-I master monitoring structure.
void reset_command_counters() const
Read some data from endpoint registers.
void write_endpoint_data(uint16_t endpoint_address, uint8_t reg_address, std::vector< uint8_t > data, bool address_mode) const
Write some data to endpoint registers.
void send_fl_cmd(uint32_t command, uint32_t channel, uint32_t number_of_commands=1) const override
Send a fixed length command.
void reset_sub_nodes(const uhal::Node &node, uint32_t aValue=0x0, bool dispatch=true) const
Reset subnodes.
std::map< std::string, uhal::ValWord< uint32_t > > read_sub_nodes(const uhal::Node &node, bool dispatch=true) const
Read subnodes.
#define TLOG_DEBUG(lvl,...)
std::string format_reg_table(T data, std::string title, std::vector< std::string > headers)
Format reg-value table.
std::string format_timestamp(uhal::ValVector< uint32_t > raw_timestamp, uint32_t clock_frequency_hz)
uint64_t tstamp2int(uhal::ValVector< uint32_t > raw_timestamp)
std::string format_counters_table(std::vector< T > counter_nodes, std::vector< std::string > counter_node_titles, std::string table_title, std::vector< std::string > counter_labels, std::string counter_labels_header)
Format reg-value table.
std::string format_reg_value(T reg_value, uint32_t base)
void millisleep(const double &time_in_milliseconds)
The opmon infrastructure has not been set up in the The control service has been defined multiple times for the application app_name you need to define only one service called control
void warning(const Issue &issue)
void info(const Issue &issue)
void error(const Issue &issue)
IntData round_trip_time_after_delay_apply
IntData state_after_delay_apply