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_;