DUDS
Distributed Update of Data from Something
DigitalPortDependentPins.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the DUDS project. It is subject to the BSD-style
3  * license terms in the LICENSE file found in the top-level directory of this
4  * distribution and at https://github.com/jjackowski/duds/blob/master/LICENSE.
5  * No part of DUDS, including this file, may be copied, modified, propagated,
6  * or distributed except according to the terms contained in the LICENSE file.
7  *
8  * Copyright (C) 2017 Jeff Jackowski
9  */
11 
12 namespace duds { namespace hardware { namespace interface {
13 
15  return false;
16 }
17 
18 // may throw from DigitalPinCap::compatible()
20  const std::vector<unsigned int> &pvec,
21  std::vector<DigitalPinConfig> &propConf,
22  std::vector<DigitalPinConfig> &initConf,
23  std::function<void(DigitalPinRejectedConfiguration::Reason)> insertReason
24 ) const {
25  // inputs must match size, except initConf may be empty
26  if ((propConf.size() != pvec.size()) || (
27  !initConf.empty() && initConf.size() != pvec.size()
28  )) {
31  );
32  }
33  // put in inital values for the starting config if empty
34  if (initConf.empty()) {
35  initConf.insert(
36  initConf.begin(),
37  pvec.size(),
39  );
40  }
41  std::vector<DigitalPinConfig> pc(pins.size()), ic(pins.size());
42  //std::vector<unsigned int> &vecp(pins.szie(), -1);
43  std::vector<bool> visited(pins.size(), false);
44  // translate from pin order in pvec to internal ordering
45  std::vector<unsigned int>::const_iterator piter = pvec.cbegin();
46  std::vector<DigitalPinConfig>::iterator pConfIter = propConf.begin();
47  std::vector<DigitalPinConfig>::iterator iConfIter = initConf.begin();
48  unsigned int pos = 0, neg = 0;
49  for (; piter != pvec.cend(); ++piter, ++pos, ++pConfIter, ++iConfIter) {
50  // multiple config check
51  if (visited[*piter]) {
53  PinErrorId(globalId(*piter)) << DigitalPortAffected(this)
54  );
55  }
56  // skip -1's
57  if (*piter == -1) {
58  ++neg;
59  }
60  // range & existence check
61  else if ((*piter < pins.size()) && (pins[*piter] || (
62  (*pConfIter == DigitalPinConfig::OperationNoChange) &&
64  ))) {
65  // move configs into internal ordered vectors
66  if (*iConfIter == DigitalPinConfig::OperationNoChange && pins[*piter]) {
67  // fill with current config
68  ic[*piter] = *iConfIter = pins[*piter].conf;
69  } else {
70  ic[*piter] = *iConfIter;
71  }
72  pc[*piter] = *pConfIter;
73  // piter has next port-local pin ID; record reverse translation
74  //vecp[*piter] = pos;
75  } //else {
76  // badness??
77  //}
78  }
79  // not all port pins specified?
80  if ((pvec.size() - neg) < pins.size()) {
81  // find and fill in missing configs with current config
82  std::vector<bool>::iterator viter = visited.begin();
83  pConfIter = pc.begin();
84  iConfIter = ic.begin();
85  PinVector::const_iterator piniter = pins.cbegin();
86  for (; viter != visited.end(); ++piter, ++pConfIter, ++iConfIter, ++piniter) {
87  // not filled?
88  if (!*viter) {
89  // use current config for the initial & proposed configs
90  *pConfIter = *iConfIter = piniter->conf;
91  }
92  }
93  }
94  bool good = true;
95  // iterate over the config in specified pin order
96  for (piter = pvec.cbegin(); piter != pvec.cend(); ++piter) {
99  // skip -1's
100  if (*piter != -1) {
101  // range & existence checks
102  if ((*piter >= pins.size()) || (!pins[*piter] && (
103  // non-existent & unsuable pins cannot be changed
104  (pc[*piter] != DigitalPinConfig::OperationNoChange) ||
106  ))) {
107  // unusable
109  } else if (pins[*piter]) {
110  // referenced pin
111  const PinEntry &pin = pins[*piter];
112  DigitalPinConfig &pconf = pc[*piter];
113  DigitalPinConfig &iconf = ic[*piter];
114  // combine options
115  pconf.reverseCombine(iconf);
116  // test compatability - may throw
118  pconf
119  );
120  // check for changes to other pins if no error yet
121  if (!err && !independentConfig(globalId(*piter), pconf, iconf)) {
122  // check how the config may alter other pins
123  err = inspectProposal(*piter, pc, ic);
124  }
125  }
126  // error?
127  if (err) {
128  // flag it for return value
129  good = false;
130  }
131  }
132  // store reason if requested
133  if (insertReason) {
134  insertReason(err);
135  }
136  }
137  // re-translate back to order in pvec
138  pConfIter = propConf.begin();
139  //iConfIter = initConf.begin();
140  piter = pvec.cbegin();
141  for (; piter != pvec.cend(); ++piter, ++pConfIter /*, ++iConfIter*/) {
142  *pConfIter = pc[*piter];
143  //*iConfIter = ic[*piter];
144  }
145  return good;
146 }
147 
149  std::vector<DigitalPinConfig> &propConf,
150  std::vector<DigitalPinConfig> &initConf,
151  std::function<void(DigitalPinRejectedConfiguration::Reason)> insertReason
152 ) const {
153  // inputs must match size of pins, except initConf may be empty
154  if ((propConf.size() != pins.size()) || (
155  !initConf.empty() && initConf.size() != pins.size()
156  )) {
158  DigitalPortAffected(this)
159  );
160  }
161  // put in inital values for the starting config if empty
162  if (initConf.empty()) {
163  initConf = configurationImpl();
164  }
165  std::vector<DigitalPinConfig>::iterator pConfIter = propConf.begin();
166  std::vector<DigitalPinConfig>::iterator iConfIter = initConf.begin();
167  PinVector::const_iterator pvIter = pins.cbegin();
168  unsigned int pos = 0;
169  bool good = true;
170  // iterate over the config
171  for (; pvIter != pins.cend(); ++pos, ++iConfIter, ++ pConfIter, ++pvIter) {
174  // non-existence check
175  if (!*pvIter && (
176  // non-existent & unsuable pins cannot be changed
177  (*pConfIter != DigitalPinConfig::OperationNoChange) ||
179  )) {
180  // unusable
182  } else if (*pvIter) {
183  // initial config unset?
184  if (*iConfIter == DigitalPinConfig::OperationNoChange) {
185  // set to current config
186  *iConfIter = pvIter->conf;
187  }
188  // combine options
189  pConfIter->reverseCombine(*iConfIter);
190  // test compatability - may throw
191  DigitalPinRejectedConfiguration::Reason err = pvIter->cap.compatible(
192  *pConfIter
193  );
194  // check for changes to other pins if no error yet
195  if (!err && !independentConfig(
196  globalId(pos),
197  *pConfIter,
198  *iConfIter
199  )) {
200  // check how the config may alter other pins
201  err = inspectProposal(pos, propConf, initConf);
202  }
203  }
204  // error?
205  if (err) {
206  // flag it for return value
207  good = false;
208  }
209  // store reason if requested
210  if (insertReason) {
211  insertReason(err);
212  }
213  }
214  return good;
215 }
216 
219  unsigned int gid,
220  DigitalPinConfig &pconf,
221  DigitalPinConfig &iconf
222 ) const {
223  // check range
224  unsigned int lid = localId(gid);
225  if ((lid >= pins.size()) || !pins[lid]) {
226  // no pin
228  }
230  // use current config
231  iconf = pins[lid].conf;
232  }
233  pconf.reverseCombine(iconf);
234  // check for an independent configuration
235  if (independentConfig(gid, pconf, iconf)) {
236  // test compatability - may throw
237  return pins[lid].cap.compatible(pconf);
238  }
239  // pass to the big proposeConfig
240  std::vector<DigitalPinConfig> propConf { pconf };
241  std::vector<DigitalPinConfig> initConf { iconf };
242  std::vector<unsigned int> pins { lid };
245  pins,
246  propConf,
247  initConf,
248  [&err](DigitalPinRejectedConfiguration::Reason e) { err = e; }
249  );
250  pconf = propConf[0];
251  return err;
252 }
253 
254 } } }
Defines the configuration for a digital general purpose I/O pin.
unsigned int localId(unsigned int globalId) const
Returns the local ID for a pin given the global ID.
constexpr Reason Unsupported
Completely unsupported.
unsigned int globalId(unsigned int localId) const
Returns the global ID for a pin given the local ID.
boost::error_info< struct Info_PinId, unsigned int > PinErrorId
The pin global ID involved in the error.
Definition: PinErrors.hpp:97
virtual DigitalPinRejectedConfiguration::Reason proposeConfigImpl(unsigned int gid, DigitalPinConfig &pconf, DigitalPinConfig &iconf) const
Considers the proposed configuration for one pin, but may consider changes to other pins if the chang...
boost::error_info< struct Info_DigitalPortAffected, const DigitalPort * > DigitalPortAffected
Added to exceptions thrown by DigitalPort objects.
void reverseCombine(const DigitalPinConfig &oldCfg)
Combines an old (initial) configuration with a new configuration in this object and stores the result...
virtual bool independentConfig() const
Some pins have a configuration that is dependent on other pins, so this function always returns false...
constexpr Reason NotRejected
There is no error with the requested pin configuration for the referenced pin.
A type-safe bit flag storage class.
Definition: BitFlags.hpp:101
virtual DigitalPinRejectedConfiguration::Reason inspectProposal(unsigned int localPinId, std::vector< DigitalPinConfig > &proposed, std::vector< DigitalPinConfig > &initial) const =0
Inspects a proposed change to the pin configuration to assure it meets all requirements and constrain...
Indicates that the specified configuration data includes too many or too few items, or has parallel data structures of inconsistent sizes.
virtual bool proposeFullConfigImpl(std::vector< DigitalPinConfig > &propConf, std::vector< DigitalPinConfig > &initConf, std::function< void(DigitalPinRejectedConfiguration::Reason)> insertReason=std::function< void(DigitalPinRejectedConfiguration::Reason)>()) const
Considers the proposed configuration one pin at a time for all pins in the port.
Indicates that an operation specified more than one configuration for a pin.
static constexpr Flags OperationNoChange
No change to any pin operation.
std::vector< DigitalPinConfig > configurationImpl() const
Returns the configuration of all pins in the port.
PinVector pins
Data on each pin handled by the port.
DigitalPinRejectedConfiguration::Reason compatible(const DigitalPinConfig &cfg) const
Returns a set of flags that indicate certain incompatible conditions in the given pin configuration i...
DigitalPinCap cap
The capabilities of the pin.
Definition: DigitalPort.hpp:83
Data stored for each pin controlled by the port.
Definition: DigitalPort.hpp:66
#define DUDS_THROW_EXCEPTION(x)
Works like BOOST_THROW_EXCEPTION, but includes a stack trace if DUDS_ERRORS_VERBOSE is defined...
Definition: Errors.hpp:48