13 namespace duds {
namespace hardware {
namespace interface {
16 pins(numpins), idOffset(firstid), waiting(0) { }
21 std::unique_lock<std::mutex> lock(
block);
23 std::vector<unsigned int> gids;
24 gids.reserve(
pins.size());
25 PinVector::iterator iter =
pins.begin();
26 for (
unsigned int gid =
idOffset; iter !=
pins.end(); ++iter, ++gid) {
51 std::lock_guard<std::mutex> lock(
block);
52 unsigned int lid =
localId(gid);
54 if ((lid >=
pins.size()) || !
pins[lid]) {
61 const std::vector<unsigned int> &
globalIds 64 localIds.reserve(globalIds.size());
65 std::vector<unsigned int>::const_iterator iter = globalIds.cbegin();
66 for (; iter != globalIds.cend(); ++iter) {
70 localIds.push_back(-1);
72 localIds.push_back(
localId(*iter));
79 const std::vector<unsigned int> &
localIds 82 globalIds.reserve(localIds.size());
83 std::vector<unsigned int>::const_iterator iter = localIds.cbegin();
84 for (; iter != localIds.cend(); ++iter) {
88 globalIds.push_back(-1);
90 globalIds.push_back(
localId(*iter));
116 for (; len; len--, reqpins++) {
118 if (*reqpins != -1) {
119 unsigned int lid =
localId(*reqpins);
121 if ((lid >=
pins.size()) || !
pins[lid]) {
137 std::unique_lock<std::mutex> &lock,
138 const unsigned int *
const reqpins,
139 const std::size_t len
161 const unsigned int *reqpins,
162 const unsigned int len,
163 std::unique_ptr<DigitalPinAccess> *acc
173 std::unique_lock<std::mutex> lock(
block);
177 for (
int i = len; i; --i, ++reqpins, ++acc) {
179 if (*reqpins != -1) {
180 unsigned int lid =
localId(*reqpins);
189 *acc = std::unique_ptr<DigitalPinAccess>(
193 pins[lid].access = acc->get();
199 for (; i <= len; ++i, --acc) {
251 const unsigned int *reqpins,
252 const unsigned int len,
263 std::unique_lock<std::mutex> lock(
block);
267 for (
int i = 0; i < len; ++i, ++reqpins) {
269 if (*reqpins != -1) {
270 unsigned int lid =
localId(*reqpins);
281 pins[lid].access = &(acc[i]);
287 for (; i >= 0; --i) {
306 const unsigned int *reqpins,
307 const unsigned int len,
319 if (acc.
port() && acc.
port() !=
this) {
325 std::unique_lock<std::mutex> lock(
block);
331 for (
int i = 0; i < len; i++, reqpins++) {
333 if (*reqpins != -1) {
334 unsigned int lid =
localId(*reqpins);
343 acc.
pinvec.push_back(lid);
345 pins[lid].access = &acc;
362 const std::vector<unsigned int> &
pins 365 access(&(pins[0]), pins.size(), *(result.get()));
374 std::lock_guard<std::mutex> lock(
block);
378 (oldAcc.
port() ==
this) &&
403 assert(oldAcc.
port() ==
this);
405 std::lock_guard<std::mutex> lock(
block);
411 std::vector<unsigned int>::const_iterator iter = oldAcc.
pinvec.begin();
412 for (; iter != oldAcc.
pinvec.end(); ++iter) {
418 (*iter <
pins.size()) &&
425 pins[*iter].access = newAcc;
435 unsigned int lid =
localId(gid);
437 std::lock_guard<std::mutex> lock(
block);
439 if ((lid >=
pins.size()) || !
pins[lid]) {
445 return pins[lid].conf;
465 unsigned int lid =
localId(gid);
467 std::lock_guard<std::mutex> lock(
block);
468 if ((lid >=
pins.size()) || !
pins[lid]) {
474 return pins[lid].cap;
479 std::lock_guard<std::mutex> lock(
block);
480 std::vector<DigitalPinCap> caps;
481 caps.reserve(
pins.size());
482 PinVector::const_iterator pin =
pins.cbegin();
483 for (; pin !=
pins.cend(); ++pin) {
484 caps.push_back(pin->cap);
490 const std::vector<unsigned int> &pvec,
bool global
493 std::lock_guard<std::mutex> lock(
block);
495 std::vector<DigitalPinCap> res;
496 res.reserve(
pins.size());
497 std::vector<unsigned int>::const_iterator iter = pvec.begin();
498 for (; iter != pvec.cend(); ++iter) {
510 if (lid >=
pins.size()) {
519 res.push_back(
pins[lid].cap);
526 std::vector<DigitalPinConfig> conf;
527 conf.reserve(
pins.size());
528 PinVector::const_iterator pin =
pins.cbegin();
529 for (; pin !=
pins.cend(); ++pin) {
530 conf.push_back(pin->conf);
537 std::lock_guard<std::mutex> lock(
block);
542 const std::vector<unsigned int> &pvec,
bool global
545 std::lock_guard<std::mutex> lock(
block);
547 std::vector<DigitalPinConfig> res;
548 res.reserve(
pins.size());
549 std::vector<unsigned int>::const_iterator iter = pvec.begin();
550 for (; iter != pvec.cend(); ++iter) {
562 if (lid >=
pins.size()) {
571 res.push_back(
pins[lid].conf);
583 std::unique_lock<std::mutex> lock(
block);
588 const std::vector<unsigned int> &
pins,
589 std::vector<DigitalPinConfig> &propConf,
590 std::vector<DigitalPinConfig> &initConf,
594 std::vector<unsigned int> local =
localIds(pins);
596 std::lock_guard<std::mutex> lock(
block);
601 const std::vector<unsigned int> &pins,
602 std::vector<DigitalPinConfig> &propConf,
603 std::vector<DigitalPinConfig> &initConf,
607 std::lock_guard<std::mutex> lock(
block);
612 std::vector<DigitalPinConfig> &propConf,
613 std::vector<DigitalPinConfig> &initConf,
617 std::lock_guard<std::mutex> lock(
block);
627 std::lock_guard<std::mutex> lock(
block);
629 unsigned int lid =
localId(gid);
630 if ((lid >= pins.size()) || !pins[lid]) {
646 pins[lid].cap.compatible(actcfg);
660 pins[lid].conf = actcfg;
664 std::vector<DigitalPinConfig> propConf(initConf);
665 propConf[lid] = actcfg;
673 std::vector<DigitalPinConfig> &propConf,
674 std::vector<DigitalPinConfig> &initConf,
678 std::vector<DigitalPinRejectedConfiguration::Reason> errs;
696 PinVector::iterator pin = pins.begin();
697 std::vector<DigitalPinConfig>::const_iterator conf = propConf.cbegin();
698 for (; conf != propConf.cend(); ++conf, ++pin) {
704 std::vector<DigitalPinConfig> &cfgs,
708 std::lock_guard<std::mutex> lock(
block);
716 const std::vector<unsigned int> &pvec,
717 std::vector<DigitalPinConfig> &cfgs,
721 if (cfgs.empty() || (cfgs.size() != pvec.size())) {
727 std::lock_guard<std::mutex> lock(
block);
730 std::vector<DigitalPinConfig> propConf = initConf;
731 std::vector<unsigned int>::const_iterator piter = pvec.begin();
732 std::vector<DigitalPinConfig>::const_iterator citer = cfgs.begin();
733 for (; piter != pvec.end(); ++citer, ++piter) {
735 if ((*piter != -1) && (*piter < pins.size()) && pins[*piter]) {
737 propConf[*piter].combine(*citer);
745 unsigned int lid =
localId(gid);
747 std::lock_guard<std::mutex> lock(
block);
750 if ((lid >= pins.size()) || !pins[lid]) {
766 const std::vector<unsigned int> &pvec,
770 std::lock_guard<std::mutex> lock(
block);
772 std::vector<unsigned int>::const_iterator piter = pvec.cbegin();
773 for (; piter != pvec.cend(); ++piter) {
776 if ((*piter >= pins.size()) || !pins[*piter]) {
794 const std::vector<unsigned int> &pvec,
800 std::vector<bool> res;
801 res.reserve(pvec.size());
802 std::vector<unsigned int>::const_iterator iter = pvec.cbegin();
803 for (
auto pid : pvec) {
814 unsigned int lid =
localId(gid);
816 std::lock_guard<std::mutex> lock(
block);
819 if ((lid >= pins.size()) || !pins[lid]) {
825 if (!pins[lid].cap.canOutput()) {
836 const std::vector<unsigned int> &pvec,
837 const std::vector<bool> &state,
841 if (pvec.size() != state.size()) {
847 std::lock_guard<std::mutex> lock(
block);
849 std::vector<unsigned int>::const_iterator piter = pvec.cbegin();
850 for (; piter != pvec.cend(); ++piter) {
853 if ((*piter >= pins.size()) || !pins[*piter]) {
859 if (!pins[*piter].cap.canOutput()) {
870 const std::vector<unsigned int> &pvec,
871 const std::vector<bool> &state,
878 std::vector<unsigned int>::const_iterator piter = pvec.cbegin();
879 std::vector<bool>::const_iterator biter = state.cbegin();
880 for (; piter != pvec.cend(); ++biter, ++piter) {
bool proposeFullConfig(std::vector< DigitalPinConfig > &propConf, std::vector< DigitalPinConfig > &initConf, std::function< void(DigitalPinRejectedConfiguration::Reason)> insertReason=std::function< void(DigitalPinRejectedConfiguration::Reason)>()) const
unsigned int localId() const
Returns the local pin ID of the accessed pin.
virtual ~DigitalPort()
Derived classes should call shutdown() early in their destructors.
boost::error_info< struct Info_DigitalPinConfig, DigitalPinConfig > DigitalPinConfigInfo
virtual bool simultaneousOperations() const =0
True if the implementation supports operating on multiple pins simultaneously.
Provides access to multiple pins on a DigitalPort.
bool input(unsigned int gid, DigitalPinAccessBase::PortData *pdata)
Does error checking in advance of calling inputImpl(unsigned int) to read the input of the given pin...
DigitalPort * port() const
Returns a pointer to the port that controls the pin(s) that are operated through this object...
std::vector< unsigned int > localIds(const std::vector< unsigned int > &globalIds) const
Converts the provided global pin IDs to local pin IDs.
static constexpr Flags DirInput
Configure the pin for input.
Defines the configuration for a digital general purpose I/O pin.
constexpr DigitalPinCap NonexistentDigitalPin
The capabilities of a non-existent pin.
bool areAvailable(const unsigned int *reqpins, std::size_t len)
Checks a set of pins to see if they are all currently available.
unsigned int localId(unsigned int globalId) const
Returns the local ID for a pin given the global ID.
boost::error_info< struct Info_DigitalPinCap, DigitalPinCap > DigitalPinCapInfo
DigitalPinConfig modifyConfig(unsigned int globalPinId, const DigitalPinConfig &cfg, DigitalPinAccessBase::PortData *pdata)
Modifies the configuration of a single pin with an independent configuration.
virtual bool independentConfig() const =0
Returns true if all pins always have an independent configuration from all other pins.
A request was made to access zero pins.
bool exists(unsigned int gid) const
Returns true if the pin exists in this port.
constexpr Reason Unsupported
Completely unsupported.
unsigned int globalId(unsigned int localId) const
Returns the global ID for a pin given the local ID.
virtual void configurePort(unsigned int localPinId, const DigitalPinConfig &cfg, DigitalPinAccessBase::PortData *pdata)=0
Changes the hardware configuration for a single pin.
void access(const unsigned int *pins, const unsigned int len, std::unique_ptr< DigitalPinAccess > *acc)
Obtain access objects to use a set of pins.
A pin required for the operation does not exist or is unavailable to the process. ...
boost::error_info< struct Info_PinId, unsigned int > PinErrorId
The pin global ID involved in the error.
A type for holding arbitrary port-specific data within a DigitalPinAccess or DigitalPinSetAccess obje...
An error indicating an attempt to use an already destructed object.
virtual void madeAccess(DigitalPinAccess &acc)
Called after a new access object is made to allow a port implementation to take further action...
boost::error_info< struct Info_DigitalPortAffected, const DigitalPort * > DigitalPortAffected
Added to exceptions thrown by DigitalPort objects.
void modifyFullConfig(std::vector< DigitalPinConfig > &propConf, std::vector< DigitalPinConfig > &initConf, DigitalPinAccessBase::PortData *pdata)
Does the work of the modifyConfig() functions in the case that the whole port configuration must be c...
friend DigitalPinSetAccess
boost::error_info< struct Info_DigitalPinRejectedConfiguration, Reason > ReasonInfo
Allows attaching the configuration rejection flags to an exception.
Indicates an error with the digital pin's configuration.
std::mutex block
Used to serialize access to internal data for thread-safe operation.
bool proposeConfigLocalIds(const std::vector< unsigned int > &localPinIds, std::vector< DigitalPinConfig > &propConf, std::vector< DigitalPinConfig > &initConf, std::function< void(DigitalPinRejectedConfiguration::Reason)> insertReason=std::function< void(DigitalPinRejectedConfiguration::Reason)>()) const
virtual bool proposeFullConfigImpl(std::vector< DigitalPinConfig > &propConf, std::vector< DigitalPinConfig > &initConf, std::function< void(DigitalPinRejectedConfiguration::Reason)> insertReason=std::function< void(DigitalPinRejectedConfiguration::Reason)>()) const =0
void reserveAdditional(unsigned int len)
Reserves additional space in pins so that upcoming pushes onto the vector will not cause multiple mem...
virtual void retiredAccess(const DigitalPinAccess &acc) noexcept
Called just before an access object is retired to allow a port implementation to take further action...
unsigned int idOffset
An offset used to translate pin identification numbers between global scope and local scope...
void shutdown()
Waits for access to all pins so that any user of access objects may finish with their operation...
std::vector< unsigned int > globalIds(const std::vector< unsigned int > &localIds) const
Converts the provided local pin IDs to global pin IDs.
An attempt was made to use a DigitalPinSetAccess object with two different DigitalPort objects...
std::vector< DigitalPinCap > capabilities() const
Returns the capabilities of all pins in the port.
void updateAccess(const DigitalPinAccess &oldAcc, DigitalPinAccess *newAcc)
Transfers or relinquishes access to pins.
Provides access to a single pin on a DigitalPort.
int waiting
A count of the threads waiting to access pins.
A type-safe bit flag storage class.
void combine(const DigitalPinConfig &newCfg)
Combines this configuration with a newer configuration taking into account requests to not change cer...
virtual void outputImpl(unsigned int lid, bool state, DigitalPinAccessBase::PortData *pdata)=0
Changes the output state of the given pin.
void output(unsigned int gid, bool state, DigitalPinAccessBase::PortData *pdata)
Does error checking in advance of calling outputImpl(unsigned int, bool) to change the output of the ...
std::condition_variable pinwait
Used to efficently wait for resources to become available.
Indicates that the specified configuration data includes too many or too few items, or has parallel data structures of inconsistent sizes.
Indicates that a request to configure a pin to output was made of a pin that cannot output...
DigitalPort(unsigned int numpins, unsigned int firstid)
Initializes internal data.
A DigitalPinAccess or DigitalPinSetAccess object cannot be obtained because one already exists with a...
DigitalPinRejectedConfiguration::Reason proposeConfig(unsigned int gid, DigitalPinConfig &pconf, DigitalPinConfig &iconf) const
Proposes a configuration change for a single pin.
Defines the capabilites of a digital general purpose I/O pin.
virtual bool inputImpl(unsigned int gid, DigitalPinAccessBase::PortData *pdata)=0
Reads input from the given pin.
static constexpr Flags OperationNoChange
No change to any pin operation.
The requested operation requires the use of the wrong, or not the current, I/O direction.
std::vector< DigitalPinConfig > configurationImpl() const
Returns the configuration of all pins in the port.
PinVector pins
Data on each pin handled by the port.
std::vector< unsigned int > pinvec
The port local pin IDs this object may use.
#define DUDS_THROW_EXCEPTION(x)
Works like BOOST_THROW_EXCEPTION, but includes a stack trace if DUDS_ERRORS_VERBOSE is defined...
std::vector< DigitalPinConfig > configuration() const
Returns the configuration of all pins in the port.
virtual DigitalPinRejectedConfiguration::Reason proposeConfigImpl(unsigned int gid, DigitalPinConfig &pconf, DigitalPinConfig &iconf) const =0
void waitForAvailability(std::unique_lock< std::mutex > &lock, const unsigned int *const reqpins, const std::size_t len)
Waits for all pins to become available.
boost::error_info< struct Info_DigitalPinRejectedConfigurationVector, std::vector< Reason >> ReasonVectorInfo