Line data Source code
1 : /** \file xtChannels.hpp
2 : * \brief Utility class for managing Acromag xt12XX digital I/O channels
3 : *
4 : * \author Jared R. Males (jaredmales@gmail.com)
5 : *
6 : * \ingroup xt1211Ctrl_files
7 : *
8 : * History:
9 : * -- Created 2019-04-21 by JRM
10 : */
11 :
12 : #ifndef xtChannels_hpp
13 : #define xtChannels_hpp
14 :
15 :
16 : /// Utility class for managing Acromag xt12XX digital I/O channels
17 : /** Reads and writes input "registers" (uint16_t) for modbus protocol.
18 : *
19 : * \tparam _numChannels is the number of channels controlled by this device.
20 : */
21 : template<int _numChannels>
22 : struct xtChannels
23 : {
24 : static constexpr int numChannels = _numChannels; ///< The number of channels controlled by the device
25 :
26 : static constexpr int numRegisters = _numChannels/4; ///< The number of registers needed for the number of channels.
27 :
28 : protected:
29 : bool m_channels[numChannels]; ///< The state of the channels
30 :
31 : bool m_inputOnly[numChannels]; ///< Control which channels can not be set to output.
32 :
33 : public:
34 :
35 : /// c'tor
36 : /** Sets m_channels and m_inputOnly to false.
37 : */
38 : xtChannels();
39 :
40 : /// Set a channel to be input only.
41 : /** A channel which is input only will not be sent as an output to the device
42 : * regardless of its state in m_channels.
43 : *
44 : * \returns 0 on success
45 : * \returns -1 on error
46 : */
47 : int setInputOnly( size_t chNo /**< [in] the channel to set to input only */ );
48 :
49 : /// Set a channel to true
50 : /**
51 : * \returns 0 on success
52 : * \returns -1 on error
53 : */
54 : int setChannel( size_t chNo /**< [in] the channel to set */ );
55 :
56 : /// Set a channel to false
57 : /**
58 : * \returns 0 on success
59 : * \returns -1 on error
60 : */
61 : int clearChannel( size_t chNo /**< [in] the channel to clear */ );
62 :
63 : /// Clear all channels
64 : /**
65 : * \returns 0 on success
66 : * \returns -1 on error
67 : */
68 : int clearAll();
69 :
70 : /// Set registers based on current channel states.
71 : /** Respects input only settings.
72 : *
73 : * \returns 0 on success
74 : * \returns -1 on error
75 : */
76 : int setRegisters( uint16_t registers[numRegisters] /**< [out] the array of registers to set */ );
77 :
78 : /// Read channel states from the registers
79 : /** This changes m_channels as they are read.
80 : *
81 : * \returns 0 on success
82 : * \returns -1 on error
83 : */
84 : int readRegisters( uint16_t registers[numRegisters] /**< [in] the array of registers to read */ );
85 :
86 : /// Gets the current state of a channel
87 : /**
88 : * \returns 0 if channel is not set
89 : * \returns 1 if channel is set
90 : * \returns -1 on error
91 : */
92 : int channel( size_t chNo /**< [in] the channel to retrieve */ );
93 :
94 : };
95 :
96 : /// Instantiaion of xtChannels for the 16-channel xt1121
97 : typedef xtChannels<16> xt1121Channels;
98 :
99 : template<int numChannels>
100 6 : xtChannels<numChannels>::xtChannels()
101 : {
102 102 : for(size_t i =0; i< numChannels; ++i)
103 : {
104 96 : m_channels[i] = false;
105 96 : m_inputOnly[i] = false;
106 : }
107 6 : }
108 :
109 : template<int numChannels>
110 54 : int xtChannels<numChannels>::setChannel( size_t chNo )
111 : {
112 54 : if(chNo > numChannels - 1) return -1;
113 :
114 54 : if(m_inputOnly[chNo])
115 : {
116 9 : m_channels[chNo] = false;
117 9 : return 0;
118 : }
119 :
120 45 : m_channels[chNo] = true;
121 :
122 45 : return 0;
123 : }
124 :
125 : template<int numChannels>
126 8 : int xtChannels<numChannels>::setInputOnly( size_t chNo )
127 : {
128 8 : if(chNo > numChannels - 1) return -1;
129 :
130 8 : m_inputOnly[chNo] = true;
131 :
132 8 : return 0;
133 : }
134 :
135 : template<int numChannels>
136 0 : int xtChannels<numChannels>::clearChannel( size_t chNo )
137 : {
138 0 : if(chNo > numChannels - 1) return -1;
139 :
140 0 : m_channels[chNo] = false;
141 :
142 0 : return 0;
143 : }
144 :
145 : template<int numChannels>
146 42 : int xtChannels<numChannels>::clearAll()
147 : {
148 714 : for(size_t i=0;i<numChannels; ++i) m_channels[i] = false;
149 :
150 42 : return 0;
151 : }
152 :
153 : template<int numChannels>
154 42 : int xtChannels<numChannels>::setRegisters( uint16_t registers[numRegisters] )
155 : {
156 210 : for(size_t i =0; i < numRegisters; ++i)
157 : {
158 168 : registers[i] = 0;
159 :
160 840 : for(size_t j=0; j < 4; ++j)
161 : {
162 672 : if(!m_inputOnly[i*4 + j])
163 : {
164 : //Set the appropriate bit for this channel if it's true.
165 588 : if(m_channels[i*4+j])
166 : {
167 45 : registers[i] += (1 << j);
168 : }
169 : }
170 : }
171 : }
172 :
173 :
174 42 : return 0;
175 : }
176 :
177 : template<int numChannels>
178 24 : int xtChannels<numChannels>::readRegisters( uint16_t registers[numRegisters] )
179 : {
180 120 : for(size_t i =0; i < numRegisters; ++i)
181 : {
182 96 : m_channels[i*4] = ((registers[i] & 1) > 0);
183 96 : m_channels[i*4+1] = ((registers[i] & 2) > 0) ;
184 96 : m_channels[i*4+2] = ((registers[i] & 4) > 0);
185 96 : m_channels[i*4+3] = ((registers[i] & 8) > 0);
186 : }
187 :
188 :
189 24 : return 0;
190 : }
191 :
192 : template<int numChannels>
193 384 : int xtChannels<numChannels>::channel( size_t chNo )
194 : {
195 384 : if(chNo > numChannels - 1) return -1;
196 :
197 384 : return m_channels[chNo];
198 :
199 : }
200 :
201 : #endif //xtChannels_hpp
202 :
|