Line data Source code
1 : /**
2 : * @file DaphneV2Interface.hpp
3 : *
4 : * Definition of the interface protocol to the daphne V2 boards
5 : *
6 : * This is part of the DUNE DAQ Software Suite, copyright 2020.
7 : * Licensing/copyright details are in the COPYING file that you should have
8 : * received with this code.
9 : *
10 : */
11 :
12 : #ifndef DAPHNEMODULES_SRC_DAPHNEV2INTERFACE_HPP_
13 : #define DAPHNEMODULES_SRC_DAPHNEV2INTERFACE_HPP_
14 :
15 : #include <arpa/inet.h>
16 : #include <cstring>
17 : #include <functional>
18 : #include <memory>
19 : #include <mutex>
20 : #include <netinet/in.h>
21 : #include <sys/socket.h>
22 : #include <unistd.h>
23 : #include <vector>
24 :
25 : #include "logging/Logging.hpp" // NOTE: if ISSUES ARE DECLARED BEFORE include logging/Logging.hpp, TLOG_DEBUG<<issue wont work.
26 : #include <ers/ers.hpp>
27 :
28 : #include "daphnemodules/CommonIssues.hpp"
29 :
30 : namespace dunedaq {
31 :
32 3 : ERS_DECLARE_ISSUE(daphnemodules, SocketCreationError, "Failed to create a socket", ERS_EMPTY)
33 :
34 3 : ERS_DECLARE_ISSUE(daphnemodules,
35 : FailedPing,
36 : "Failed to ping daphne board at " << ip << ':' << port,
37 : ((std::string)ip)((int)port))
38 :
39 3 : ERS_DECLARE_ISSUE(daphnemodules, FailedSocketInteraction, "Failed to call " << command, ((std::string)command))
40 :
41 3 : ERS_DECLARE_ISSUE(daphnemodules,
42 : CommandTimeout,
43 : "Command " << command << " timed out after " << timeout_us << " microseconds",
44 : ((std::string)command)((unsigned int)timeout_us))
45 :
46 3 : ERS_DECLARE_ISSUE(daphnemodules,
47 : SocketTimeout,
48 : "Socket timed out after " << timeout_us << " microseconds",
49 : ((unsigned int)timeout_us))
50 :
51 : } // dunedaq namespace
52 :
53 : namespace dunedaq::daphnemodules {
54 :
55 : struct command_result
56 : {
57 : std::string command;
58 : std::string result;
59 : };
60 :
61 : class DaphneV2Interface
62 : {
63 :
64 : public:
65 : DaphneV2Interface(const char* ipaddr, int port, std::chrono::milliseconds timeout = std::chrono::milliseconds(500));
66 :
67 0 : ~DaphneV2Interface()
68 : {
69 0 : if (m_connection_id > 0)
70 0 : close();
71 0 : }
72 :
73 : DaphneV2Interface(const DaphneV2Interface&) = delete;
74 : DaphneV2Interface& operator=(const DaphneV2Interface&) = delete;
75 : DaphneV2Interface(DaphneV2Interface&&) = delete;
76 : DaphneV2Interface& operator=(DaphneV2Interface&&) = delete;
77 :
78 0 : std::vector<uint64_t> read_register(uint64_t addr, uint8_t size) const { return read(0x00, addr, size); }
79 0 : void write_register(uint64_t addr, std::vector<uint64_t>&& data) const { write(0x01, addr, std::move(data)); }
80 :
81 0 : std::vector<uint64_t> read_buffer(uint64_t addr, uint8_t size) const { return read(0x08, addr, size); }
82 0 : void write_buffer(uint64_t addr, std::vector<uint64_t>&& data) const { write(0x09, addr, std::move(data)); }
83 :
84 : bool validate_connection() const;
85 :
86 : command_result send_command(std::string cmd) const;
87 :
88 : // this will throw if it fails
89 : command_result send_command_retry(std::string cmd, size_t retry = std::numeric_limits<size_t>::max()) const;
90 :
91 : // this will try until success but it won't thrwo if can retry become false
92 : command_result send_command_interruptible(std::string cmd, std::function<bool()> can_retry) const;
93 :
94 : protected:
95 : void close();
96 :
97 : void write(uint8_t command_id, uint64_t addr, std::vector<uint64_t>&& data) const;
98 : std::vector<uint64_t> read(uint8_t command_id, uint64_t addr, uint8_t size) const;
99 :
100 : private:
101 : std::string m_ip;
102 : int m_connection_id = -1;
103 : sockaddr_in m_target;
104 : std::chrono::milliseconds m_timeout{ 5 };
105 : mutable std::mutex m_access_mutex;
106 : mutable std::mutex m_command_mutex;
107 : };
108 :
109 : } // namespce dunedaq::daphnemodules
110 :
111 : #endif // DAPHNEMODULES_SRC_DAPHNEV2INTERFACE_HPP_
|