Convert BufferedSolenoid to use HAL.

Change-Id: Ibb1f5d800923b340a4632ad79611442dc54aec34
diff --git a/frc971/wpilib/buffered_pcm.cc b/frc971/wpilib/buffered_pcm.cc
index 5f1dc67..bd52079 100644
--- a/frc971/wpilib/buffered_pcm.cc
+++ b/frc971/wpilib/buffered_pcm.cc
@@ -2,11 +2,25 @@
 
 #include <inttypes.h>
 
+#include <HAL/HAL.h>
+#include <HAL/Ports.h>
+#include <HAL/Solenoid.h>
 #include "aos/common/logging/logging.h"
 
 namespace frc971 {
 namespace wpilib {
 
+BufferedPcm::BufferedPcm(int module) : module_(module) {
+  for (int i = 0; i < 8; ++i) {
+    int32_t status = 0;
+    solenoid_handles_[i] =
+        HAL_InitializeSolenoidPort(HAL_GetPortWithModule(module_, i), &status);
+    if (status != 0) {
+      LOG(FATAL, "Status was %d\n", status);
+    }
+  }
+}
+
 ::std::unique_ptr<BufferedSolenoid> BufferedPcm::MakeSolenoid(int number) {
   return ::std::unique_ptr<BufferedSolenoid>(
       new BufferedSolenoid(number, this));
@@ -20,13 +34,23 @@
   }
 }
 
+int32_t BufferedPcm::GetAll() {
+  int32_t status = 0;
+  int32_t result = HAL_GetAllSolenoids(module_, &status);
+  if (status != 0) {
+    LOG(ERROR, "Failed to flush, %d\n", status);
+    return 0;
+  }
+  return result;
+}
+
 void BufferedPcm::Flush() {
   LOG(DEBUG, "sending solenoids 0x%" PRIx8 "\n", values_);
-#ifdef WPILIB2017
-  SolenoidBase::SetAll(values_, m_moduleNumber);
-#else
-  SolenoidBase::Set(values_, 0xFF, m_moduleNumber);
-#endif
+  int32_t status = 0;
+  HAL_SetAllSolenoids(module_, static_cast<int>(values_), &status);
+  if (status != 0) {
+    LOG(ERROR, "Failed to flush, %d\n", status);
+  }
 }
 
 }  // namespace wpilib
diff --git a/frc971/wpilib/buffered_pcm.h b/frc971/wpilib/buffered_pcm.h
index 4ff625b..877e830 100644
--- a/frc971/wpilib/buffered_pcm.h
+++ b/frc971/wpilib/buffered_pcm.h
@@ -3,8 +3,7 @@
 
 #include <memory>
 
-#include "Solenoid.h"
-#undef ERROR
+#include <HAL/HAL.h>
 
 #include "frc971/wpilib/buffered_solenoid.h"
 
@@ -17,24 +16,28 @@
 // The way to use this is to call MakeSolenoid for whichever solenoid numbers
 // you want, call Set on those, and then periodically call Flush on this object
 // to write all of the buffered values out.
-class BufferedPcm : public Solenoid {
+class BufferedPcm {
  public:
-  explicit BufferedPcm() : Solenoid(0) {}
+  explicit BufferedPcm(int module = 0);
 
   // Creates a new BufferedSolenoid for a specified port number.
   ::std::unique_ptr<BufferedSolenoid> MakeSolenoid(int number);
 
+  // Returns a bitmask of the state of all the solenoids.
+  int32_t GetAll();
+
   // Actually sends all of the values out.
   void Flush();
 
  private:
-  // WPILib declares this pure virtual and then never calls it...
-#ifdef WPILIB2015
-  virtual void InitSolenoid() override {}
-#endif
-
   void DoSet(int number, bool value);
 
+  int module_;
+  ::std::array<HAL_SolenoidHandle, 8> solenoid_handles_{
+      {HAL_kInvalidHandle, HAL_kInvalidHandle, HAL_kInvalidHandle,
+       HAL_kInvalidHandle, HAL_kInvalidHandle, HAL_kInvalidHandle,
+       HAL_kInvalidHandle, HAL_kInvalidHandle}};
+
   uint8_t values_ = 0;
 
   friend class BufferedSolenoid;