Squashed 'third_party/allwpilib_2017/' content from commit 35ac87d

Change-Id: I7bb6f5556c30d3f5a092e68de0be9c710c60c9f4
git-subtree-dir: third_party/allwpilib_2017
git-subtree-split: 35ac87d6ff8b7f061c4f18c9ea316e5dccd4888a
diff --git a/wpilibc/athena/src/ADXL362.cpp b/wpilibc/athena/src/ADXL362.cpp
new file mode 100644
index 0000000..4a4d0c8
--- /dev/null
+++ b/wpilibc/athena/src/ADXL362.cpp
@@ -0,0 +1,182 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008-2017. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#include "ADXL362.h"
+
+#include "DigitalInput.h"
+#include "DigitalOutput.h"
+#include "DriverStation.h"
+#include "HAL/HAL.h"
+#include "LiveWindow/LiveWindow.h"
+
+using namespace frc;
+
+static int kRegWrite = 0x0A;
+static int kRegRead = 0x0B;
+
+static int kPartIdRegister = 0x02;
+static int kDataRegister = 0x0E;
+static int kFilterCtlRegister = 0x2C;
+static int kPowerCtlRegister = 0x2D;
+
+// static int kFilterCtl_Range2G = 0x00;
+// static int kFilterCtl_Range4G = 0x40;
+// static int kFilterCtl_Range8G = 0x80;
+static int kFilterCtl_ODR_100Hz = 0x03;
+
+static int kPowerCtl_UltraLowNoise = 0x20;
+// static int kPowerCtl_AutoSleep = 0x04;
+static int kPowerCtl_Measure = 0x02;
+
+/**
+ * Constructor.  Uses the onboard CS1.
+ *
+ * @param range The range (+ or -) that the accelerometer will measure.
+ */
+ADXL362::ADXL362(Range range) : ADXL362(SPI::Port::kOnboardCS1, range) {}
+
+/**
+ * Constructor.
+ *
+ * @param port  The SPI port the accelerometer is attached to
+ * @param range The range (+ or -) that the accelerometer will measure.
+ */
+ADXL362::ADXL362(SPI::Port port, Range range) : m_spi(port) {
+  m_spi.SetClockRate(3000000);
+  m_spi.SetMSBFirst();
+  m_spi.SetSampleDataOnFalling();
+  m_spi.SetClockActiveLow();
+  m_spi.SetChipSelectActiveLow();
+
+  // Validate the part ID
+  uint8_t commands[3];
+  commands[0] = kRegRead;
+  commands[1] = kPartIdRegister;
+  commands[2] = 0;
+  m_spi.Transaction(commands, commands, 3);
+  if (commands[2] != 0xF2) {
+    DriverStation::ReportError("could not find ADXL362");
+    m_gsPerLSB = 0.0;
+    return;
+  }
+
+  SetRange(range);
+
+  // Turn on the measurements
+  commands[0] = kRegWrite;
+  commands[1] = kPowerCtlRegister;
+  commands[2] = kPowerCtl_Measure | kPowerCtl_UltraLowNoise;
+  m_spi.Write(commands, 3);
+
+  HAL_Report(HALUsageReporting::kResourceType_ADXL362, port);
+
+  LiveWindow::GetInstance()->AddSensor("ADXL362", port, this);
+}
+
+void ADXL362::SetRange(Range range) {
+  if (m_gsPerLSB == 0.0) return;
+
+  uint8_t commands[3];
+
+  switch (range) {
+    case kRange_2G:
+      m_gsPerLSB = 0.001;
+      break;
+    case kRange_4G:
+      m_gsPerLSB = 0.002;
+      break;
+    case kRange_8G:
+    case kRange_16G:  // 16G not supported; treat as 8G
+      m_gsPerLSB = 0.004;
+      break;
+  }
+
+  // Specify the data format to read
+  commands[0] = kRegWrite;
+  commands[1] = kFilterCtlRegister;
+  commands[2] =
+      kFilterCtl_ODR_100Hz | static_cast<uint8_t>((range & 0x03) << 6);
+  m_spi.Write(commands, 3);
+}
+
+double ADXL362::GetX() { return GetAcceleration(kAxis_X); }
+
+double ADXL362::GetY() { return GetAcceleration(kAxis_Y); }
+
+double ADXL362::GetZ() { return GetAcceleration(kAxis_Z); }
+
+/**
+ * Get the acceleration of one axis in Gs.
+ *
+ * @param axis The axis to read from.
+ * @return Acceleration of the ADXL362 in Gs.
+ */
+double ADXL362::GetAcceleration(ADXL362::Axes axis) {
+  if (m_gsPerLSB == 0.0) return 0.0;
+
+  uint8_t buffer[4];
+  uint8_t command[4] = {0, 0, 0, 0};
+  command[0] = kRegRead;
+  command[1] = kDataRegister + static_cast<uint8_t>(axis);
+  m_spi.Transaction(command, buffer, 4);
+
+  // Sensor is little endian... swap bytes
+  int16_t rawAccel = buffer[3] << 8 | buffer[2];
+  return rawAccel * m_gsPerLSB;
+}
+
+/**
+ * Get the acceleration of all axes in Gs.
+ *
+ * @return An object containing the acceleration measured on each axis of the
+ *         ADXL362 in Gs.
+ */
+ADXL362::AllAxes ADXL362::GetAccelerations() {
+  AllAxes data = AllAxes();
+  if (m_gsPerLSB == 0.0) {
+    data.XAxis = data.YAxis = data.ZAxis = 0.0;
+    return data;
+  }
+
+  uint8_t dataBuffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+  int16_t rawData[3];
+
+  // Select the data address.
+  dataBuffer[0] = kRegRead;
+  dataBuffer[1] = kDataRegister;
+  m_spi.Transaction(dataBuffer, dataBuffer, 8);
+
+  for (int i = 0; i < 3; i++) {
+    // Sensor is little endian... swap bytes
+    rawData[i] = dataBuffer[i * 2 + 3] << 8 | dataBuffer[i * 2 + 2];
+  }
+
+  data.XAxis = rawData[0] * m_gsPerLSB;
+  data.YAxis = rawData[1] * m_gsPerLSB;
+  data.ZAxis = rawData[2] * m_gsPerLSB;
+
+  return data;
+}
+
+std::string ADXL362::GetSmartDashboardType() const {
+  return "3AxisAccelerometer";
+}
+
+void ADXL362::InitTable(std::shared_ptr<ITable> subtable) {
+  m_table = subtable;
+  UpdateTable();
+}
+
+void ADXL362::UpdateTable() {
+  if (m_table != nullptr) {
+    m_table->PutNumber("X", GetX());
+    m_table->PutNumber("Y", GetY());
+    m_table->PutNumber("Z", GetZ());
+  }
+}
+
+std::shared_ptr<ITable> ADXL362::GetTable() const { return m_table; }