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 disable_timestamp_broadcast();
303 TLOG() <<
"Timestamp broadcast disabled";
305 set_timestamp(source);
307 enable_timestamp_broadcast();
308 TLOG() <<
"Timestamp broadcast enabled";
316 return getNode<TimestampGeneratorNode>(
"tstamp").read_timestamp();
324 getNode<TimestampGeneratorNode>(
"tstamp").set_timestamp(source);
336 getClient().dispatch();
339 mon_data.
ts_valid = state.at(
"ts_valid").value();
340 mon_data.
ts_tx_err = state.at(
"ts_tx_err").value();
341 mon_data.
tx_err = state.at(
"tx_err").value();
342 mon_data.
ctrs_rdy = state.at(
"ctrs_rdy").value();
373 auto global = getNode<MasterGlobalNode>(
"global");
374 global.reset_command_counters();
387 for (
auto t : packet)
390 getNode(
"acmd_buf.txbuf").writeBlock(packet);
391 getClient().dispatch();
396 std::vector<uint32_t> empty_vector;
400 uhal::ValWord<uint32_t> buffer_ready;
401 uhal::ValWord<uint32_t> buffer_timeout;
404 auto start = std::chrono::high_resolution_clock::now();
409 buffer_ready = getNode(
"acmd_buf.stat.ready").read();
410 buffer_timeout = getNode(
"acmd_buf.stat.timeout").read();
411 getClient().dispatch();
413 TLOG_DEBUG(10) <<
"async buffer ready: 0x" << buffer_ready.value() <<
", timeout: " << buffer_timeout.value();
416 throw VLCommandReplyTimeout(
ERS_HERE);
421 auto now = std::chrono::high_resolution_clock::now();
422 auto us_since_start = std::chrono::duration_cast<std::chrono::microseconds>(
now - start);
424 if (us_since_start.count() > timeout)
425 throw VLCommandReplyBufferFlagTimeout(
ERS_HERE, timeout);
427 std::this_thread::sleep_for(std::chrono::microseconds(50));
430 auto rx_packet = getNode(
"acmd_buf.rxbuf").readBlock(0x20);
431 getClient().dispatch();
433 if (rx_packet.at(0) != 0xff || rx_packet.at(1) != 0xff || rx_packet.at(2) != packet.at(2))
435 ers::warning(InvalidVLCommandReplyPacket(
ERS_HERE, rx_packet.at(0), rx_packet.at(1), rx_packet.at(2)));
439 for (
auto r : rx_packet)
442 return rx_packet.value();
450 auto data_length = data.size();
451 if (data_length > 0x3f || data_length == 0)
453 TLOG() <<
"invalid data length";
457 uint32_t sequence = 0xab;
459 std::vector<uint32_t> tx_packet = {
static_cast<uint32_t
>(endpoint_address & 0xff),
460 static_cast<uint32_t
>(endpoint_address >> 8UL),
463 static_cast<uint32_t
>((0x1 << 7UL) | reg_address),
464 static_cast<uint32_t
>((address_mode << 7UL) | (0x3f & data_length))
466 tx_packet.insert(tx_packet.end(), data.begin(), data.end());
467 tx_packet.back() = tx_packet.back() | (0x1 << 8UL);
477 if (data_length > 0x3f || data_length == 0)
479 TLOG() <<
"invalid data length";
484 uint32_t sequence = 0xab;
485 std::vector<uint32_t> tx_packet = {
static_cast<uint32_t
>(endpoint_address & 0xff),
486 static_cast<uint32_t
>(endpoint_address >> 8UL),
490 static_cast<uint32_t
>((0x1 << 8UL) | (address_mode << 7UL) | (0x3f & data_length))
496 std::vector<uint32_t> result_data (result.begin()+3, result.begin()+3+data_length);
499 result_data.back() = result_data.back() & 0xff;
508 getNode(
"global.csr.ctrl.ts_en").write(0x0);
509 getClient().dispatch();
516 getNode(
"global.csr.ctrl.ts_en").write(0x1);
517 getClient().dispatch();
526 auto global = getNode<MasterGlobalNode>(
"global");
527 auto echo = getNode<EchoMonitorNode>(
"echo_mon");
530 endpoint_result.
address = endpoint_address;
543 global.enable_upstream_endpoint();
545 catch (
const timing::ReceiverNotReady& e)
551 return endpoint_result;
554 endpoint_result.
alive =
true;
559 TLOG_DEBUG(5) <<
"Endpoint at address " << endpoint_address <<
" state: 0x" << std::hex << ept_state;
560 endpoint_result.
state = ept_state;
562 if (ept_state == 0x6)
564 TLOG_DEBUG(5) <<
"Endpoint at address " << endpoint_address <<
", applying delays of: " << 0x0;
565 ers::info(MonitoredEndpointDelaySet(
ERS_HERE, 0x0, endpoint_address, ept_state));
570 auto ept_state_after_delays =
read_endpoint_data(endpoint_address, 0x71, 0x1, 0x1).at(0) & 0xf;
571 TLOG_DEBUG(5) <<
"Endpoint at address " << endpoint_address <<
", state after delays apply: " << ept_state_after_delays;
577 else if (ept_state == 0x7 || ept_state == 0x8)
579 TLOG_DEBUG(5) <<
"Endpoint at address " << endpoint_address <<
", delays not needed";
591 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)
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