wip. got started sanifying stuff
diff --git a/aos/crio/hardware/README b/aos/crio/hardware/README
new file mode 100644
index 0000000..551de5c
--- /dev/null
+++ b/aos/crio/hardware/README
@@ -0,0 +1,8 @@
+This directory contains replacements/wrappers for WPILib classes.
+
+Be careful using the classes that have the same names as WPILib ones! Many of
+ them bring in the declarations for the WPILib ones which means you have to
+ qualify the names of these ones (and should do the same for WPILib ones too).
+The wrappers only have the functionality that is missing from whatever WPILib
+ class they are wrapping (and can return pointer to). Use that pointer to do
+ everything else.
diff --git a/aos/crio/hardware/counter.cc b/aos/crio/hardware/counter.cc
new file mode 100644
index 0000000..25ec6aa
--- /dev/null
+++ b/aos/crio/hardware/counter.cc
@@ -0,0 +1,54 @@
+#include "aos/crio/hardware/hardware.h"
+
+#include "aos/crio/hardware/digital_source.h"
+
+using ::std::unique_ptr;
+
+namespace aos {
+namespace crio {
+namespace hardware {
+
+int Counter::GetDenominator() {
+ switch (type_) {
+ case ::CounterBase::EncodingType::k1X:
+ return 1;
+ case ::CounterBase::EncodingType::k2X:
+ return 2;
+ case ::CounterBase::EncodingType::k4X:
+ return 4;
+ }
+}
+
+unique_ptr<Counter> Counter::Create(unique_ptr<DigitalSource> a,
+ unique_ptr<DigitalSource> b,
+ ::CounterBase::EncodingType type) {
+ switch (type) {
+ case ::CounterBase::EncodingType::k4X:
+ return unique_ptr<Counter>(new EncoderCounter(::std::move(a),
+ ::std::move(b)));
+ case ::CounterBase::EncodingTYpe::k2X:
+ case ::CounterBase::EncodingType::k1X:
+ return unique_ptr<Counter>(new CounterCounter(::std::move(a),
+ ::std::move(b),
+ type));
+ }
+}
+
+EncoderCounter::EncoderCounter(unique_ptr<DigitalSource> a,
+ unique_ptr<DigitalSource> b)
+ : Counter(::std::move(a), ::std::move(b), ::CounterBase::EncodingType::k4X),
+ encoder_(new ::Encoder(a()->source(), b()->source())) {}
+
+CounterCounter::CounterCounter(unique_ptr<DigitalSource> a,
+ unique_ptr<DigitalSource> b,
+ ::CounterBase::EncodingType type)
+ : Counter(::std::move(a), ::std::move(b), type),
+ counter_(new ::Counter(type, a()->source(), b()->source(),
+ false /*inverted*/)) {
+ assert(type == ::CounterBase::EncodingType::k1X ||
+ type == ::CounterBase::EncodingType::k2X);
+}
+
+} // namespace hardware
+} // namespace crio
+} // namespace aos
diff --git a/aos/crio/hardware/counter.h b/aos/crio/hardware/counter.h
new file mode 100644
index 0000000..f184146
--- /dev/null
+++ b/aos/crio/hardware/counter.h
@@ -0,0 +1,96 @@
+#ifndef AOS_CRIO_HARDWARE_ENCODER_H_
+#define AOS_CRIO_HARDWARE_ENCODER_H_
+
+#include "aos/common/libstdc++/memory"
+
+#include "WPILib/Counter.h"
+#include "WPILib/CounterBase.h"
+#include "WPILib/Encoder.h"
+
+#include "aos/common/macros.h"
+
+namespace aos {
+namespace crio {
+namespace hardware {
+
+class DigitalSource;
+
+// Wrapper for WPILib's CounterBase that implements Get() consistently.
+// WPILib doesn't really differentiate between (and actually confuses) ticks and
+// cycles. There is 1 tick for each input edge that a Counter sees and 1 cycle
+// every time the inputs repeat their pattern.
+// The constructors for both of them are such a mess that these classes
+// intentionally do not support using them. Instead, just call the constructors
+// for these classes and let them handle using the correct constructor.
+class Counter {
+ public:
+ virtual ~Counter() {}
+
+ // Returns the number of ticks (NOT divided by the number of ticks per
+ // cycle like WPILib _sometimes_ is!).
+ virtual int32_t Get() = 0;
+ // This object maintains ownership.
+ virtual ::CounterBase *counter_base() const = 0;
+
+ const ::std::unique_ptr<DigitalSource> &a() { return a_; }
+ const ::std::unique_ptr<DigitalSource> &b() { return b_; }
+
+ // Returns the denominator to convert from ticks to cycles.
+ int GetDenominator();
+
+ // Will create an instance of a subclass as appropriate for type.
+ // This should be used (except for special circumstances) for constructing all
+ // instances because it makes it much easier to change the encoding type.
+ static ::std::unique_ptr<Counter> Create(::std::unique_ptr<DigitalSource> a,
+ ::std::unique_ptr<DigitalSource> b,
+ ::CounterBase::EncodingType type);
+
+ protected:
+ Counter(::std::unique_ptr<DigitalSource> a,
+ ::std::unique_ptr<DigitalSource> b,
+ ::CounterBase::EncodingType type)
+ : a_(::std::move(a)),
+ b_(::std::move(b)),
+ type_(type) {}
+
+ private:
+ // Because WPILib doesn't actually keep track of it...
+ const ::CounterBase::EncodingType type_;
+
+ const ::std::unique_ptr<DigitalSource> a_;
+ const ::std::unique_ptr<DigitalSource> b_;
+
+ DISALLOW_COPY_AND_ASSIGN(Counter);
+};
+
+// Only allows creating one with k4X decoding because otherwise ::Encoder just
+// creates an internal ::Counter, which is really stupid.
+class EncoderCounter : public Counter {
+ public:
+ EncoderCounter(::std::unique_ptr<DigitalSource> a,
+ ::std::unique_ptr<DigitalSource> b);
+
+ virtual int32_t Get() { return encoder_->GetRaw(); }
+ virtual ::CounterBase *counter_base() { return encoder_.get(); }
+
+ private:
+ const ::std::unique_ptr<Encoder> encoder_;
+};
+
+class CounterCounter : public Counter {
+ public:
+ CounterCounter(::std::unique_ptr<DigitalSource> a,
+ ::std::unique_ptr<DigitalSource> b,
+ ::CounterBase::EncodingType type);
+
+ virtual int32_t Get() { return counter_->Get(); }
+ virtual ::CounterBase *counter_base() { return counter_.get(); }
+
+ private:
+ const ::std::unique_ptr<Counter> counter_;
+
+} // namespace hardware
+} // namespace crio
+} // namespace aos
+
+#endif // AOS_CRIO_HARDWARE_ENCODER_H_
diff --git a/aos/crio/hardware/digital_source.cc b/aos/crio/hardware/digital_source.cc
new file mode 100644
index 0000000..83f6142
--- /dev/null
+++ b/aos/crio/hardware/digital_source.cc
@@ -0,0 +1,17 @@
+#include "aos/crio/hardware/digital_source.h"
+
+namespace aos {
+namespace crio {
+namespace hardware {
+
+AnalogTriggerOutput::AnalogTriggerOutput(const ::AnalogTrigger &trigger,
+ ::AnalogTriggerOutput::Type type,
+ float lowerVoltage,
+ float upperVoltage)
+ : output_(trigger.CreateOutput(type)) {
+ trigger.SetLimitsVoltage(lowerVoltage, upperVoltage);
+}
+
+} // namespace hardware
+} // namespace crio
+} // namespace aos
diff --git a/aos/crio/hardware/digital_source.h b/aos/crio/hardware/digital_source.h
new file mode 100644
index 0000000..9bc5cab
--- /dev/null
+++ b/aos/crio/hardware/digital_source.h
@@ -0,0 +1,69 @@
+#ifndef AOS_CRIO_HARDWARE_DIGITAL_SOURCE_H_
+#define AOS_CRIO_HARDWARE_DIGITAL_SOURCE_H_
+
+#include "aos/common/libstdc++/memory"
+
+#include "WPILib/DigitalSource.h"
+#include "WPILib/DigitalInput.h"
+#include "WPILib/AnalogTrigger.h"
+#include "WPILib/AnalogTriggerOutput.h"
+
+#include "aos/common/macros.h"
+
+namespace aos {
+namespace crio {
+namespace hardware {
+
+// Wrapper for WPILib's class of the same name. Provides an actual Get()
+// function and makes creating analog ones easier.
+class DigitalSource {
+ public:
+ virtual ~DigitalSource() {}
+
+ virtual bool Get() = 0;
+ // This object maintains ownership.
+ virtual ::DigitalSource *source() const = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DigitalSource);
+};
+
+class AnalogTriggerOutput : public DigitalSource {
+ public:
+ // Defaults for the voltages for AnalogTriggers. They work well for digital
+ // sensors connected to analog inputs.
+ static const float kDefaultLowerVoltage = 1;
+ static const float kDefaultUpperVoltage = 4;
+
+ // Will set up the voltages on trigger.
+ AnalogTriggerOutput(const ::AnalogTrigger &trigger,
+ ::AnalogTriggerOutput::Type type,
+ float lowerVoltage = kDefaultLowerVoltage,
+ float upperVoltage = kDefaultUpperVoltage);
+ AnalogTriggerOutput(::std::unique_ptr<::AnalogTriggerOutput> output)
+ : output_(::std::move(output)) {}
+
+ virtual bool Get() { return output_->Get(); }
+ virtual ::DigitalSource *source() const { return output_.get(); }
+
+ private:
+ const ::std::unique_ptr<::AnalogTriggerOutput> output_;
+};
+
+class DigitalInput : public DigitalSource {
+ public:
+ DigitalInput(::std::unique_ptr<::DigitalInput> input)
+ : input_(::std::move(input)) {}
+
+ virtual bool Get() { return input_->Get(); }
+ virtual ::DigitalSource *source() const { return input_.get(); }
+
+ private:
+ const ::std::unique_ptr<::DigitalInput> input_;
+};
+
+} // namespace hardware
+} // namespace crio
+} // namespace aos
+
+#endif // AOS_CRIO_HARDWARE_DIGITAL_SOURCE_H_
diff --git a/aos/crio/hardware/hardware.gyp b/aos/crio/hardware/hardware.gyp
new file mode 100644
index 0000000..44cbb89
--- /dev/null
+++ b/aos/crio/hardware/hardware.gyp
@@ -0,0 +1,31 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'digital_source',
+ 'type': 'static_library',
+ 'sources': [
+ 'digital_source.cc',
+ ],
+ 'dependencies': [
+ '<(EXTERNALS):WPILib',
+ ],
+ 'export_dependent_settings': [
+ '<(EXTERNALS):WPILib',
+ ],
+ },
+ {
+ 'target_name': 'counter',
+ 'type': 'static_library',
+ 'sources': [
+ 'counter.cc',
+ ],
+ 'dependencies': [
+ 'digital_source',
+ '<(EXTERNALS):WPILib',
+ ],
+ 'export_dependent_settings': [
+ '<(EXTERNALS):WPILib',
+ ],
+ },
+ ],
+}
diff --git a/aos/crio/shared_libs/limit_encoder_reader.cc b/aos/crio/shared_libs/limit_encoder_reader.cc
index 3d49269..f8c5b55 100644
--- a/aos/crio/shared_libs/limit_encoder_reader.cc
+++ b/aos/crio/shared_libs/limit_encoder_reader.cc
@@ -51,11 +51,11 @@
}
void LimitEncoderReader::Init(unique_ptr<AnalogChannel> channel,
- AnalogTriggerOutput::Type type,
- AnalogTriggerOutput::Type triggeredType,
- bool posEdge, bool negEdge,
- float lowerVoltage,
- float upperVoltage) {
+ AnalogTriggerOutput::Type type,
+ AnalogTriggerOutput::Type triggeredType,
+ bool posEdge, bool negEdge,
+ float lowerVoltage,
+ float upperVoltage) {
unique_ptr<AnalogTrigger> trigger(new AnalogTrigger(channel.get()));
trigger->SetLimitsVoltage(lowerVoltage, upperVoltage);
source_ = unique_ptr<AnalogTriggerOutput>(trigger->CreateOutput(type));
diff --git a/aos/crio/shared_libs/limit_encoder_reader.h b/aos/crio/shared_libs/limit_encoder_reader.h
index d8eab7d..fe68190 100644
--- a/aos/crio/shared_libs/limit_encoder_reader.h
+++ b/aos/crio/shared_libs/limit_encoder_reader.h
@@ -13,6 +13,9 @@
#include "aos/common/zero_switch_value.h"
#include "aos/common/macros.h"
#include "aos/crio/shared_libs/interrupt_notifier.h"
+#include "aos/crio/hardware/digital_source.h"
+#include "aos/crio/hardware/counter.h"
+// TODO(brians): fix the build file
namespace aos {
namespace crio {
@@ -21,59 +24,15 @@
// triggers, including all of the irritating WPILib setup and synchronization.
class LimitEncoderReader {
public:
- // Defaults for the voltages for AnalogTriggers. They work well for digital
- // sensors connected to analog inputs.
- static const float kDefaultLowerVoltage = 1;
- static const float kDefaultUpperVoltage = 4;
-
// See InterruptNotifier for details about the state of the sensor object
// before the constructor is called.
- // The different constructors take in different types of inputs and configure
- // them to give interrupts.
- // There are separate (very similar) constructors for Encoder and Counter
- // because they implement CounterBase::Get() differently, making it useless...
- //
- // type is the type for triggering interrupts while triggeredType is the one
- // to use for writing *triggered in Get().
- // AnalogTriggerOutput::Type::k*Pulse don't seem to do anything...
- LimitEncoderReader(const ::std::unique_ptr<Encoder> &encoder,
- ::std::unique_ptr<AnalogChannel> channel,
- AnalogTriggerOutput::Type type,
- AnalogTriggerOutput::Type triggeredType,
- bool posEdge, bool negEdge,
- float lowerVoltage = kDefaultLowerVoltage,
- float upperVoltage = kDefaultUpperVoltage)
- : encoder_(new EncoderCountGetter(encoder)) {
- Init(::std::move(channel), type, triggeredType, posEdge, negEdge,
- lowerVoltage, upperVoltage);
- }
- LimitEncoderReader(const ::std::unique_ptr<Counter> &counter,
- ::std::unique_ptr<AnalogChannel> channel,
- AnalogTriggerOutput::Type type,
- AnalogTriggerOutput::Type triggeredType,
- bool posEdge, bool negEdge,
- float lowerVoltage = kDefaultLowerVoltage,
- float upperVoltage = kDefaultUpperVoltage)
- : encoder_(new CounterCountGetter(counter)) {
- Init(::std::move(channel), type, triggeredType, posEdge, negEdge,
- lowerVoltage, upperVoltage);
- }
- LimitEncoderReader(const ::std::unique_ptr<Encoder> &encoder,
- ::std::unique_ptr<DigitalInput> sensor,
- bool posEdge, bool negEdge)
- : encoder_(new EncoderCountGetter(encoder)) {
- Init(::std::move(sensor), posEdge, negEdge);
- }
- LimitEncoderReader(const ::std::unique_ptr<Counter> &counter,
- ::std::unique_ptr<DigitalInput> sensor,
- bool posEdge, bool negEdge)
- : encoder_(new CounterCountGetter(counter)) {
- Init(::std::move(sensor), posEdge, negEdge);
- }
-
+ LimitEncoderReader(::std::unique_ptr<::aos::crio::hardware::Counter> counter,
+ ::std::uniuqe_ptr<::aos::crio::hardware::DigitalSource>
+ source,
+ bool posEdge, bool negEdge);
// Retrieves the values. See ZeroSwitchValue's declaration for an explanation
- // of why retrieving all of them is necessary.
+ // of why retrieving all of them at once is necessary.
ZeroSwitchValue Get();
// Calls Start() on all owned objects.
@@ -82,70 +41,15 @@
// Only to set things up etc. Getting values through these methods will always
// have race conditions!
// Also helpful for debugging.
- const ::std::unique_ptr<DigitalSource> &source() const {
+ const ::std::unique_ptr<::aos::crio::hardware::Counter> &counter() const {
+ return counter_;
+ }
+ const ::std::unique_ptr<::aos::crio::hardware::DigitalSource>
+ &source() const {
return source_;
}
private:
- // A class to deal with the fact that WPILib's AnalogTriggerOutput and
- // DigitalInput have no common superclass with their Get() functions.
- // Also handles taking ownership of some attached objects for
- // AnalogTriggerOutput.
- class OnOffGetter {
- public:
- virtual bool Get() = 0;
-
- virtual ~OnOffGetter() {}
- };
- class AnalogOnOffGetter;
- class DigitalOnOffGetter;
-
- // A class to deal with the fact that WPILib's Encoder and Counter have no
- // common superclass with the function that we want to use for getting the
- // number of ticks.
- class CountGetter {
- public:
- virtual int32_t Get() = 0;
-
- virtual ~CountGetter() {}
- };
- class EncoderCountGetter : public CountGetter {
- public:
- EncoderCountGetter(const ::std::unique_ptr<Encoder> &counter)
- : counter_(counter) {}
-
- virtual int32_t Get();
-
- private:
- const ::std::unique_ptr<Encoder> &counter_;
- };
- class CounterCountGetter : public CountGetter {
- public:
- CounterCountGetter(const ::std::unique_ptr<Counter> &counter)
- : counter_(counter) {}
-
- virtual int32_t Get();
-
- private:
- const ::std::unique_ptr<Counter> &counter_;
- };
-
- // Separate initialization functions for each of the main constructor
- // variants. encoder_ must be set before calling this.
- void Init(::std::unique_ptr<AnalogChannel> channel,
- AnalogTriggerOutput::Type type,
- AnalogTriggerOutput::Type triggeredType,
- bool posEdge, bool negEdge,
- float lowerVoltage,
- float upperVoltage);
- void Init(::std::unique_ptr<DigitalInput> source,
- bool posEdge, bool negEdge);
-
- // The common initialization code.
- // Gets called by all of the constructors.
- // getter_, encoder_, and source_ must be set before calling this.
- void CommonInit(bool posEdge, bool negEdge);
-
static void ReadValueStatic(LimitEncoderReader *self) {
self->ReadValue();
}
@@ -154,8 +58,8 @@
::std::unique_ptr<InterruptNotifier<LimitEncoderReader>> notifier_;
const ::std::unique_ptr<CountGetter> encoder_;
- ::std::unique_ptr<OnOffGetter> getter_;
- ::std::unique_ptr<DigitalSource> source_;
+ ::std::unique_ptr<::aos::crio::hardware::Counter> counter_;
+ ::std::unique_ptr<::aos::crio::hardware::DigitalSource> source_;
// The most recently read value.
int32_t value_;