Line data Source code
1 : /**
2 : * @file I2CMasterNode.hpp
3 : * @class I2CMasterNode
4 : *
5 : * @brief OpenCode I2C interface to a ipbus node
6 : * @author Kristian Harder, Alessandro Thea
7 : * @date August 2013
8 : *
9 : * The class is non-copyable on purpose as the inheriting object
10 : * must properly set the node pointer in the copy i2c access through
11 : * an IPbus interface.
12 : *
13 : * I2CMasterNode is a class providing an interface
14 : * to the I2C master firmware block.
15 : *
16 : * This is part of the DUNE DAQ Software Suite, copyright 2020.
17 : * Licensing/copyright details are in the COPYING file that you should have
18 : * received with this code.
19 : */
20 :
21 : #ifndef TIMING_INCLUDE_TIMING_I2CMASTERNODE_HPP_
22 : #define TIMING_INCLUDE_TIMING_I2CMASTERNODE_HPP_
23 :
24 : #include "timing/TimingNode.hpp"
25 :
26 : // uHal Headers
27 : #include "TimingIssues.hpp"
28 : #include "ers/Issue.hpp"
29 : #include "uhal/DerivedNode.hpp"
30 :
31 : #include <string>
32 : #include <unordered_map>
33 : #include <vector>
34 :
35 : namespace dunedaq {
36 : namespace timing {
37 :
38 : class I2CSlave;
39 :
40 : class I2CMasterNode : public uhal::Node
41 : {
42 : UHAL_DERIVEDNODE(I2CMasterNode)
43 : public:
44 : explicit I2CMasterNode(const uhal::Node& node);
45 : I2CMasterNode(const I2CMasterNode& node);
46 : virtual ~I2CMasterNode();
47 :
48 : ///
49 0 : virtual uint16_t get_i2c_clock_prescale() const { return m_clock_prescale; } // NOLINT(build/unsigned)
50 :
51 : virtual std::vector<std::string> get_slaves() const;
52 : virtual uint8_t get_slave_address(const std::string& name) const; // NOLINT(build/unsigned)
53 : virtual const I2CSlave& get_slave(const std::string& name) const;
54 :
55 : void reset() const;
56 :
57 : /// commodity functions
58 : virtual uint8_t read_i2c(uint8_t i2c_device_address, uint32_t i2c_reg_address, bool atomic = false) const; // NOLINT(build/unsigned)
59 : virtual void write_i2c(uint8_t i2c_device_address, // NOLINT(build/unsigned)
60 : uint32_t i2c_reg_address, // NOLINT(build/unsigned)
61 : uint8_t data, // NOLINT(build/unsigned)
62 : bool send_stop = true) const;
63 :
64 : virtual std::vector<uint8_t> read_i2cArray(uint8_t i2c_device_address, // NOLINT(build/unsigned)
65 : uint32_t i2c_reg_address, // NOLINT(build/unsigned)
66 : uint32_t number_of_words, // NOLINT(build/unsigned)
67 : bool atomic = false) const; // NOLINT(build/unsigned)
68 : virtual void write_i2cArray(uint8_t i2c_device_address, // NOLINT(build/unsigned)
69 : uint32_t i2c_reg_address, // NOLINT(build/unsigned)
70 : std::vector<uint8_t> data, // NOLINT(build/unsigned)
71 : bool send_stop = true) const;
72 :
73 : virtual std::vector<uint8_t> read_i2cPrimitive(uint8_t i2c_device_address, // NOLINT(build/unsigned)
74 : uint32_t number_of_bytes) const; // NOLINT(build/unsigned)
75 : virtual void write_i2cPrimitive(uint8_t i2c_device_address, // NOLINT(build/unsigned)
76 : const std::vector<uint8_t>& data, // NOLINT(build/unsigned)
77 : bool send_stop = true) const;
78 :
79 : bool ping(uint8_t i2c_device_address, bool throw_excp = false) const; // NOLINT(build/unsigned)
80 :
81 : std::vector<uint8_t> scan() const; // NOLINT(build/unsigned)
82 :
83 : protected:
84 : // low level i2c functions
85 : std::vector<uint8_t> virtual read_block_i2c(uint8_t i2c_device_address, // NOLINT(build/unsigned)
86 : uint32_t number_of_bytes, // NOLINT(build/unsigned)
87 : bool send_reset = true) const;
88 : void virtual write_block_i2c(uint8_t i2c_device_address, // NOLINT(build/unsigned)
89 : const std::vector<uint8_t>& data, // NOLINT(build/unsigned)
90 : bool send_stop = true) const;
91 :
92 : uint8_t send_i2c_command_and_read_data(uint8_t command) const; // NOLINT(build/unsigned)
93 : void send_i2c_command_and_write_data(uint8_t command, uint8_t data) const; // NOLINT(build/unsigned)
94 :
95 : //! Slaves
96 : std::unordered_map<std::string, uint8_t> m_i2c_device_addresses; // NOLINT(build/unsigned)
97 :
98 : private:
99 : ///
100 : void constructor();
101 :
102 : // low level i2c functions
103 : void wait_until_finished(bool require_acknowledgement = true, bool require_bus_idle_at_end = false) const;
104 :
105 : //! IPBus register names for i2c bus
106 : static const std::string kPreHiNode;
107 : static const std::string kPreLoNode;
108 : static const std::string kCtrlNode;
109 : static const std::string kTxNode;
110 : static const std::string kRxNode;
111 : static const std::string kCmdNode;
112 : static const std::string kStatusNode;
113 :
114 : static const uint8_t kStartCmd; // 1 << 7 // NOLINT(build/unsigned)
115 : static const uint8_t kStopCmd; // 1 << // NOLINT(build/unsigned)
116 : static const uint8_t kReadFromSlaveCmd; // 1 << 5 // NOLINT(build/unsigned)
117 : static const uint8_t kWriteToSlaveCmd; // 1 << 4 // NOLINT(build/unsigned)
118 : static const uint8_t kAckCmd; // 1 << 3 // NOLINT(build/unsigned)
119 : static const uint8_t kInterruptAck; // 1 // NOLINT(build/unsigned)
120 :
121 : static const uint8_t kReceivedAckBit; // recvdack = 0x1 << 7 // NOLINT(build/unsigned)
122 : static const uint8_t kBusyBit; // busy = 0x1 << 6 // NOLINT(build/unsigned)
123 : static const uint8_t kArbitrationLostBit; // arblost = 0x1 << 5 // NOLINT(build/unsigned)
124 : static const uint8_t kInProgressBit; // inprogress = 0x1 << 1 // NOLINT(build/unsigned)
125 : static const uint8_t kInterruptBit; // interrupt = 0x1 // NOLINT(build/unsigned)
126 :
127 : //! clock prescale factor
128 : uint16_t m_clock_prescale; // NOLINT(build/unsigned)
129 :
130 : //! I2C slaves attached to this node
131 : std::unordered_map<std::string, I2CSlave*>
132 : m_i2c_devices; // TODO, Eric Flumerfelt <eflumerf@fnal.gov> May-21-2021: Consider using smart pointers
133 :
134 : friend class I2CSlave;
135 : };
136 :
137 : } // namespace timing
138 : } // namespace dunedaq
139 :
140 : #endif // TIMING_INCLUDE_TIMING_I2CMASTERNODE_HPP_
|