Line data Source code
1 : /**
2 : * @file TimingController.cpp TimingController class
3 : * implementation
4 : *
5 : * This is part of the DUNE DAQ Software Suite, copyright 2020.
6 : * Licensing/copyright details are in the COPYING file that you should have
7 : * received with this code.
8 : */
9 :
10 : #include "timinglibs/TimingController.hpp"
11 : #include "timinglibs/timingcmd/Nljs.hpp"
12 : #include "timinglibs/timingcmd/Structs.hpp"
13 : #include "timinglibs/timingcmd/msgp.hpp"
14 : #include "timinglibs/TimingIssues.hpp"
15 :
16 : #include "appfwk/cmd/Nljs.hpp"
17 : #include "ers/Issue.hpp"
18 : #include "iomanager/IOManager.hpp"
19 : #include "logging/Logging.hpp"
20 : #include "confmodel/Connection.hpp"
21 :
22 : #include <chrono>
23 : #include <cstdlib>
24 : #include <string>
25 : #include <thread>
26 : #include <vector>
27 :
28 : namespace dunedaq {
29 :
30 0 : DUNE_DAQ_SERIALIZABLE(timinglibs::timingcmd::TimingHwCmd, "TimingHwCmd");
31 0 : DUNE_DAQ_SERIALIZABLE(nlohmann::json, "JSON");
32 :
33 : namespace timinglibs {
34 :
35 0 : TimingController::TimingController(const std::string& name, uint number_hw_commands)
36 : : dunedaq::appfwk::DAQModule(name)
37 0 : , m_hw_command_out_connection("timing_cmds")
38 0 : , m_hw_cmd_out_timeout(100)
39 0 : , m_hw_command_sender(nullptr)
40 0 : , m_timing_device("")
41 0 : , m_timing_session_name("")
42 0 : , m_device_info_receiver(nullptr)
43 0 : , m_number_hw_commands(number_hw_commands)
44 0 : , m_sent_hw_command_counters(m_number_hw_commands)
45 0 : , m_device_ready_timeout(10000)
46 0 : , m_device_ready(false)
47 0 : , m_device_infos_received_count(0)
48 0 : , m_hardware_state_recovery_enabled(false)
49 : {
50 0 : for (auto it = m_sent_hw_command_counters.begin(); it != m_sent_hw_command_counters.end(); ++it) {
51 0 : it->atomic.store(0);
52 : }
53 :
54 0 : register_command("io_reset", &TimingController::do_io_reset);
55 0 : register_command("print_status", &TimingController::do_print_status);
56 0 : }
57 :
58 : void
59 0 : TimingController::init(std::shared_ptr<appfwk::ConfigurationManager> mcfg)
60 : {
61 0 : auto mod_config = mcfg->get_dal<dal::TimingController>(get_name());
62 0 : m_params = mod_config->get_configuration();
63 0 : }
64 :
65 : void
66 0 : TimingController::do_configure(const CommandData_t& /*data*/)
67 : {
68 0 : m_timing_device = m_params->get_device();
69 0 : m_hardware_state_recovery_enabled = m_params->get_hardware_state_recovery_enabled();
70 0 : m_timing_session_name = m_params->get_timing_session_name();
71 :
72 0 : if (m_timing_device.empty())
73 : {
74 0 : throw UHALDeviceNameIssue(ERS_HERE, "Device name should not be empty");
75 : }
76 :
77 0 : if (!m_hw_command_out_connection.empty())
78 : {
79 0 : if (m_timing_session_name.empty())
80 : {
81 0 : m_hw_command_sender = iomanager::IOManager::get()->get_sender<timingcmd::TimingHwCmd>(m_hw_command_out_connection);
82 : }
83 : else
84 : {
85 0 : m_hw_command_sender = iomanager::IOManager::get()->get_sender<timingcmd::TimingHwCmd>(
86 0 : iomanager::ConnectionId{m_hw_command_out_connection, datatype_to_string<timingcmd::TimingHwCmd>(), m_timing_session_name} );
87 : }
88 :
89 0 : if (m_timing_session_name.empty())
90 : {
91 0 : m_device_info_receiver = iomanager::IOManager::get()->get_receiver<nlohmann::json>(m_timing_device+"_info");
92 : }
93 : else
94 : {
95 0 : m_device_info_receiver = iomanager::IOManager::get()->get_receiver<nlohmann::json>(
96 0 : iomanager::ConnectionId{m_timing_device+"_info", datatype_to_string<nlohmann::json>(), m_timing_session_name});
97 : }
98 0 : m_device_info_receiver->add_callback(std::bind(&TimingController::process_device_info, this, std::placeholders::_1));
99 : }
100 0 : }
101 :
102 : void
103 0 : TimingController::do_scrap(const CommandData_t&)
104 : {
105 0 : if (m_device_info_receiver)
106 : {
107 0 : m_device_info_receiver->remove_callback();
108 : }
109 0 : m_device_infos_received_count=0;
110 0 : m_device_ready = false;
111 :
112 0 : for (auto it = m_sent_hw_command_counters.begin(); it != m_sent_hw_command_counters.end(); ++it)
113 : {
114 0 : it->atomic.store(0);
115 : }
116 0 : }
117 :
118 : void
119 0 : TimingController::send_hw_cmd(timingcmd::TimingHwCmd&& hw_cmd)
120 : {
121 0 : if (!m_hw_command_sender)
122 : {
123 0 : throw QueueIsNullFatalError(ERS_HERE, get_name(), m_hw_command_out_connection);
124 : }
125 0 : try {
126 0 : m_hw_command_sender->send(std::move(hw_cmd), m_hw_cmd_out_timeout);
127 0 : } catch (const dunedaq::iomanager::TimeoutExpired& excpt) {
128 0 : std::ostringstream oss_warn;
129 0 : oss_warn << "push to output queue \"" << m_hw_command_out_connection << "\"";
130 0 : ers::warning(dunedaq::iomanager::TimeoutExpired(
131 0 : ERS_HERE,
132 0 : get_name(),
133 0 : oss_warn.str(),
134 0 : std::chrono::duration_cast<std::chrono::milliseconds>(m_hw_cmd_out_timeout).count()));
135 0 : }
136 0 : }
137 :
138 : timingcmd::TimingHwCmd
139 0 : TimingController::construct_hw_cmd( const std::string& cmd_id)
140 : {
141 0 : timingcmd::TimingHwCmd hw_cmd;
142 0 : hw_cmd.id = cmd_id;
143 0 : hw_cmd.device = m_timing_device;
144 0 : return hw_cmd;
145 0 : }
146 :
147 : timingcmd::TimingHwCmd
148 0 : TimingController::construct_hw_cmd( const std::string& cmd_id, const nlohmann::json& payload)
149 : {
150 0 : auto hw_cmd = construct_hw_cmd(cmd_id);
151 0 : hw_cmd.payload = payload;
152 0 : return hw_cmd;
153 0 : }
154 :
155 : void
156 0 : TimingController::do_io_reset(const CommandData_t& data)
157 : {
158 0 : timingcmd::TimingHwCmd hw_cmd =
159 0 : construct_hw_cmd( "io_reset", data);
160 :
161 0 : hw_cmd.payload["clock_source"] = m_params->get_clock_source();
162 0 : hw_cmd.payload["soft"] = m_params->get_soft();
163 :
164 0 : send_hw_cmd(std::move(hw_cmd));
165 0 : ++(m_sent_hw_command_counters.at(0).atomic);
166 0 : }
167 :
168 : void
169 0 : TimingController::do_print_status(const CommandData_t&)
170 : {
171 0 : timingcmd::TimingHwCmd hw_cmd =
172 0 : construct_hw_cmd( "print_status");
173 0 : send_hw_cmd(std::move(hw_cmd));
174 0 : ++(m_sent_hw_command_counters.at(1).atomic);
175 0 : }
176 :
177 : } // namespace timinglibs
178 : } // namespace dunedaq
179 :
180 : // Local Variables:
181 : // c-basic-offset: 2
182 : // End:
|