Squashed 'third_party/allwpilib_2019/' content from commit bd05dfa1c
Change-Id: I2b1c2250cdb9b055133780c33593292098c375b7
git-subtree-dir: third_party/allwpilib_2019
git-subtree-split: bd05dfa1c7cca74c4fac451e7b9d6a37e7b53447
diff --git a/wpilibc/src/dev/native/cpp/main.cpp b/wpilibc/src/dev/native/cpp/main.cpp
new file mode 100644
index 0000000..6e64d2b
--- /dev/null
+++ b/wpilibc/src/dev/native/cpp/main.cpp
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 <iostream>
+
+#include <hal/HAL.h>
+
+#include "WPILibVersion.h"
+
+int main() {
+ std::cout << "Hello World" << std::endl;
+ std::cout << HAL_GetRuntimeType() << std::endl;
+ std::cout << GetWPILibVersion() << std::endl;
+ return 0;
+}
diff --git a/wpilibc/src/generate/WPILibVersion.cpp.in b/wpilibc/src/generate/WPILibVersion.cpp.in
new file mode 100644
index 0000000..b0a4490
--- /dev/null
+++ b/wpilibc/src/generate/WPILibVersion.cpp.in
@@ -0,0 +1,7 @@
+/*
+ * Autogenerated file! Do not manually edit this file. This version is regenerated
+ * any time the publish task is run, or when this file is deleted.
+ */
+const char* GetWPILibVersion() {
+ return "${wpilib_version}";
+}
diff --git a/wpilibc/src/main/native/cpp/ADXL345_I2C.cpp b/wpilibc/src/main/native/cpp/ADXL345_I2C.cpp
new file mode 100644
index 0000000..71407da
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/ADXL345_I2C.cpp
@@ -0,0 +1,69 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/ADXL345_I2C.h"
+
+#include <hal/HAL.h>
+
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+ADXL345_I2C::ADXL345_I2C(I2C::Port port, Range range, int deviceAddress)
+ : m_i2c(port, deviceAddress) {
+ // Turn on the measurements
+ m_i2c.Write(kPowerCtlRegister, kPowerCtl_Measure);
+ // Specify the data format to read
+ SetRange(range);
+
+ HAL_Report(HALUsageReporting::kResourceType_ADXL345,
+ HALUsageReporting::kADXL345_I2C, 0);
+ SetName("ADXL345_I2C", port);
+}
+
+void ADXL345_I2C::SetRange(Range range) {
+ m_i2c.Write(kDataFormatRegister,
+ kDataFormat_FullRes | static_cast<uint8_t>(range));
+}
+
+double ADXL345_I2C::GetX() { return GetAcceleration(kAxis_X); }
+
+double ADXL345_I2C::GetY() { return GetAcceleration(kAxis_Y); }
+
+double ADXL345_I2C::GetZ() { return GetAcceleration(kAxis_Z); }
+
+double ADXL345_I2C::GetAcceleration(ADXL345_I2C::Axes axis) {
+ int16_t rawAccel = 0;
+ m_i2c.Read(kDataRegister + static_cast<int>(axis), sizeof(rawAccel),
+ reinterpret_cast<uint8_t*>(&rawAccel));
+ return rawAccel * kGsPerLSB;
+}
+
+ADXL345_I2C::AllAxes ADXL345_I2C::GetAccelerations() {
+ AllAxes data = AllAxes();
+ int16_t rawData[3];
+ m_i2c.Read(kDataRegister, sizeof(rawData),
+ reinterpret_cast<uint8_t*>(rawData));
+
+ data.XAxis = rawData[0] * kGsPerLSB;
+ data.YAxis = rawData[1] * kGsPerLSB;
+ data.ZAxis = rawData[2] * kGsPerLSB;
+ return data;
+}
+
+void ADXL345_I2C::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("3AxisAccelerometer");
+ auto x = builder.GetEntry("X").GetHandle();
+ auto y = builder.GetEntry("Y").GetHandle();
+ auto z = builder.GetEntry("Z").GetHandle();
+ builder.SetUpdateTable([=]() {
+ auto data = GetAccelerations();
+ nt::NetworkTableEntry(x).SetDouble(data.XAxis);
+ nt::NetworkTableEntry(y).SetDouble(data.YAxis);
+ nt::NetworkTableEntry(z).SetDouble(data.ZAxis);
+ });
+}
diff --git a/wpilibc/src/main/native/cpp/ADXL345_SPI.cpp b/wpilibc/src/main/native/cpp/ADXL345_SPI.cpp
new file mode 100644
index 0000000..738bc3e
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/ADXL345_SPI.cpp
@@ -0,0 +1,97 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/ADXL345_SPI.h"
+
+#include <hal/HAL.h>
+
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+ADXL345_SPI::ADXL345_SPI(SPI::Port port, ADXL345_SPI::Range range)
+ : m_spi(port) {
+ m_spi.SetClockRate(500000);
+ m_spi.SetMSBFirst();
+ m_spi.SetSampleDataOnTrailingEdge();
+ m_spi.SetClockActiveLow();
+ m_spi.SetChipSelectActiveHigh();
+
+ uint8_t commands[2];
+ // Turn on the measurements
+ commands[0] = kPowerCtlRegister;
+ commands[1] = kPowerCtl_Measure;
+ m_spi.Transaction(commands, commands, 2);
+
+ SetRange(range);
+
+ HAL_Report(HALUsageReporting::kResourceType_ADXL345,
+ HALUsageReporting::kADXL345_SPI);
+
+ SetName("ADXL345_SPI", port);
+}
+
+void ADXL345_SPI::SetRange(Range range) {
+ uint8_t commands[2];
+
+ // Specify the data format to read
+ commands[0] = kDataFormatRegister;
+ commands[1] = kDataFormat_FullRes | static_cast<uint8_t>(range & 0x03);
+ m_spi.Transaction(commands, commands, 2);
+}
+
+double ADXL345_SPI::GetX() { return GetAcceleration(kAxis_X); }
+
+double ADXL345_SPI::GetY() { return GetAcceleration(kAxis_Y); }
+
+double ADXL345_SPI::GetZ() { return GetAcceleration(kAxis_Z); }
+
+double ADXL345_SPI::GetAcceleration(ADXL345_SPI::Axes axis) {
+ uint8_t buffer[3];
+ uint8_t command[3] = {0, 0, 0};
+ command[0] = (kAddress_Read | kAddress_MultiByte | kDataRegister) +
+ static_cast<uint8_t>(axis);
+ m_spi.Transaction(command, buffer, 3);
+
+ // Sensor is little endian... swap bytes
+ int16_t rawAccel = buffer[2] << 8 | buffer[1];
+ return rawAccel * kGsPerLSB;
+}
+
+ADXL345_SPI::AllAxes ADXL345_SPI::GetAccelerations() {
+ AllAxes data = AllAxes();
+ uint8_t dataBuffer[7] = {0, 0, 0, 0, 0, 0, 0};
+ int16_t rawData[3];
+
+ // Select the data address.
+ dataBuffer[0] = (kAddress_Read | kAddress_MultiByte | kDataRegister);
+ m_spi.Transaction(dataBuffer, dataBuffer, 7);
+
+ for (int i = 0; i < 3; i++) {
+ // Sensor is little endian... swap bytes
+ rawData[i] = dataBuffer[i * 2 + 2] << 8 | dataBuffer[i * 2 + 1];
+ }
+
+ data.XAxis = rawData[0] * kGsPerLSB;
+ data.YAxis = rawData[1] * kGsPerLSB;
+ data.ZAxis = rawData[2] * kGsPerLSB;
+
+ return data;
+}
+
+void ADXL345_SPI::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("3AxisAccelerometer");
+ auto x = builder.GetEntry("X").GetHandle();
+ auto y = builder.GetEntry("Y").GetHandle();
+ auto z = builder.GetEntry("Z").GetHandle();
+ builder.SetUpdateTable([=]() {
+ auto data = GetAccelerations();
+ nt::NetworkTableEntry(x).SetDouble(data.XAxis);
+ nt::NetworkTableEntry(y).SetDouble(data.YAxis);
+ nt::NetworkTableEntry(z).SetDouble(data.ZAxis);
+ });
+}
diff --git a/wpilibc/src/main/native/cpp/ADXL362.cpp b/wpilibc/src/main/native/cpp/ADXL362.cpp
new file mode 100644
index 0000000..d709ae4
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/ADXL362.cpp
@@ -0,0 +1,152 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/ADXL362.h"
+
+#include <hal/HAL.h>
+
+#include "frc/DriverStation.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+static constexpr int kRegWrite = 0x0A;
+static constexpr int kRegRead = 0x0B;
+
+static constexpr int kPartIdRegister = 0x02;
+static constexpr int kDataRegister = 0x0E;
+static constexpr int kFilterCtlRegister = 0x2C;
+static constexpr int kPowerCtlRegister = 0x2D;
+
+// static constexpr int kFilterCtl_Range2G = 0x00;
+// static constexpr int kFilterCtl_Range4G = 0x40;
+// static constexpr int kFilterCtl_Range8G = 0x80;
+static constexpr int kFilterCtl_ODR_100Hz = 0x03;
+
+static constexpr int kPowerCtl_UltraLowNoise = 0x20;
+// static constexpr int kPowerCtl_AutoSleep = 0x04;
+static constexpr int kPowerCtl_Measure = 0x02;
+
+ADXL362::ADXL362(Range range) : ADXL362(SPI::Port::kOnboardCS1, range) {}
+
+ADXL362::ADXL362(SPI::Port port, Range range) : m_spi(port) {
+ m_spi.SetClockRate(3000000);
+ m_spi.SetMSBFirst();
+ m_spi.SetSampleDataOnTrailingEdge();
+ 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);
+
+ SetName("ADXL362", port);
+}
+
+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); }
+
+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;
+}
+
+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;
+}
+
+void ADXL362::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("3AxisAccelerometer");
+ auto x = builder.GetEntry("X").GetHandle();
+ auto y = builder.GetEntry("Y").GetHandle();
+ auto z = builder.GetEntry("Z").GetHandle();
+ builder.SetUpdateTable([=]() {
+ auto data = GetAccelerations();
+ nt::NetworkTableEntry(x).SetDouble(data.XAxis);
+ nt::NetworkTableEntry(y).SetDouble(data.YAxis);
+ nt::NetworkTableEntry(z).SetDouble(data.ZAxis);
+ });
+}
diff --git a/wpilibc/src/main/native/cpp/ADXRS450_Gyro.cpp b/wpilibc/src/main/native/cpp/ADXRS450_Gyro.cpp
new file mode 100644
index 0000000..875f403
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/ADXRS450_Gyro.cpp
@@ -0,0 +1,109 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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 "frc/ADXRS450_Gyro.h"
+
+#include <hal/HAL.h>
+
+#include "frc/DriverStation.h"
+#include "frc/Timer.h"
+
+using namespace frc;
+
+static constexpr double kSamplePeriod = 0.0005;
+static constexpr double kCalibrationSampleTime = 5.0;
+static constexpr double kDegreePerSecondPerLSB = 0.0125;
+
+static constexpr int kRateRegister = 0x00;
+static constexpr int kTemRegister = 0x02;
+static constexpr int kLoCSTRegister = 0x04;
+static constexpr int kHiCSTRegister = 0x06;
+static constexpr int kQuadRegister = 0x08;
+static constexpr int kFaultRegister = 0x0A;
+static constexpr int kPIDRegister = 0x0C;
+static constexpr int kSNHighRegister = 0x0E;
+static constexpr int kSNLowRegister = 0x10;
+
+ADXRS450_Gyro::ADXRS450_Gyro() : ADXRS450_Gyro(SPI::kOnboardCS0) {}
+
+ADXRS450_Gyro::ADXRS450_Gyro(SPI::Port port) : m_spi(port) {
+ m_spi.SetClockRate(3000000);
+ m_spi.SetMSBFirst();
+ m_spi.SetSampleDataOnLeadingEdge();
+ m_spi.SetClockActiveHigh();
+ m_spi.SetChipSelectActiveLow();
+
+ // Validate the part ID
+ if ((ReadRegister(kPIDRegister) & 0xff00) != 0x5200) {
+ DriverStation::ReportError("could not find ADXRS450 gyro");
+ return;
+ }
+
+ m_spi.InitAccumulator(kSamplePeriod, 0x20000000u, 4, 0x0c00000eu, 0x04000000u,
+ 10u, 16u, true, true);
+
+ Calibrate();
+
+ HAL_Report(HALUsageReporting::kResourceType_ADXRS450, port);
+ SetName("ADXRS450_Gyro", port);
+}
+
+static bool CalcParity(int v) {
+ bool parity = false;
+ while (v != 0) {
+ parity = !parity;
+ v = v & (v - 1);
+ }
+ return parity;
+}
+
+static inline int BytesToIntBE(uint8_t* buf) {
+ int result = static_cast<int>(buf[0]) << 24;
+ result |= static_cast<int>(buf[1]) << 16;
+ result |= static_cast<int>(buf[2]) << 8;
+ result |= static_cast<int>(buf[3]);
+ return result;
+}
+
+uint16_t ADXRS450_Gyro::ReadRegister(int reg) {
+ int cmd = 0x80000000 | static_cast<int>(reg) << 17;
+ if (!CalcParity(cmd)) cmd |= 1u;
+
+ // big endian
+ uint8_t buf[4] = {static_cast<uint8_t>((cmd >> 24) & 0xff),
+ static_cast<uint8_t>((cmd >> 16) & 0xff),
+ static_cast<uint8_t>((cmd >> 8) & 0xff),
+ static_cast<uint8_t>(cmd & 0xff)};
+
+ m_spi.Write(buf, 4);
+ m_spi.Read(false, buf, 4);
+ if ((buf[0] & 0xe0) == 0) return 0; // error, return 0
+ return static_cast<uint16_t>((BytesToIntBE(buf) >> 5) & 0xffff);
+}
+
+double ADXRS450_Gyro::GetAngle() const {
+ return m_spi.GetAccumulatorIntegratedValue() * kDegreePerSecondPerLSB;
+}
+
+double ADXRS450_Gyro::GetRate() const {
+ return static_cast<double>(m_spi.GetAccumulatorLastValue()) *
+ kDegreePerSecondPerLSB;
+}
+
+void ADXRS450_Gyro::Reset() { m_spi.ResetAccumulator(); }
+
+void ADXRS450_Gyro::Calibrate() {
+ Wait(0.1);
+
+ m_spi.SetAccumulatorIntegratedCenter(0);
+ m_spi.ResetAccumulator();
+
+ Wait(kCalibrationSampleTime);
+
+ m_spi.SetAccumulatorIntegratedCenter(m_spi.GetAccumulatorIntegratedAverage());
+ m_spi.ResetAccumulator();
+}
diff --git a/wpilibc/src/main/native/cpp/AnalogAccelerometer.cpp b/wpilibc/src/main/native/cpp/AnalogAccelerometer.cpp
new file mode 100644
index 0000000..3ae8e48
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/AnalogAccelerometer.cpp
@@ -0,0 +1,62 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/AnalogAccelerometer.h"
+
+#include <hal/HAL.h>
+
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+AnalogAccelerometer::AnalogAccelerometer(int channel)
+ : AnalogAccelerometer(std::make_shared<AnalogInput>(channel)) {
+ AddChild(m_analogInput);
+}
+
+AnalogAccelerometer::AnalogAccelerometer(AnalogInput* channel)
+ : m_analogInput(channel, NullDeleter<AnalogInput>()) {
+ if (channel == nullptr) {
+ wpi_setWPIError(NullParameter);
+ } else {
+ InitAccelerometer();
+ }
+}
+
+AnalogAccelerometer::AnalogAccelerometer(std::shared_ptr<AnalogInput> channel)
+ : m_analogInput(channel) {
+ if (channel == nullptr) {
+ wpi_setWPIError(NullParameter);
+ } else {
+ InitAccelerometer();
+ }
+}
+
+double AnalogAccelerometer::GetAcceleration() const {
+ return (m_analogInput->GetAverageVoltage() - m_zeroGVoltage) / m_voltsPerG;
+}
+
+void AnalogAccelerometer::SetSensitivity(double sensitivity) {
+ m_voltsPerG = sensitivity;
+}
+
+void AnalogAccelerometer::SetZero(double zero) { m_zeroGVoltage = zero; }
+
+double AnalogAccelerometer::PIDGet() { return GetAcceleration(); }
+
+void AnalogAccelerometer::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Accelerometer");
+ builder.AddDoubleProperty("Value", [=]() { return GetAcceleration(); },
+ nullptr);
+}
+
+void AnalogAccelerometer::InitAccelerometer() {
+ HAL_Report(HALUsageReporting::kResourceType_Accelerometer,
+ m_analogInput->GetChannel());
+ SetName("Accelerometer", m_analogInput->GetChannel());
+}
diff --git a/wpilibc/src/main/native/cpp/AnalogGyro.cpp b/wpilibc/src/main/native/cpp/AnalogGyro.cpp
new file mode 100644
index 0000000..5efe7b3
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/AnalogGyro.cpp
@@ -0,0 +1,173 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/AnalogGyro.h"
+
+#include <climits>
+#include <utility>
+
+#include <hal/AnalogGyro.h>
+#include <hal/Errors.h>
+#include <hal/HAL.h>
+
+#include "frc/AnalogInput.h"
+#include "frc/Timer.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+AnalogGyro::AnalogGyro(int channel)
+ : AnalogGyro(std::make_shared<AnalogInput>(channel)) {
+ AddChild(m_analog);
+}
+
+AnalogGyro::AnalogGyro(AnalogInput* channel)
+ : AnalogGyro(
+ std::shared_ptr<AnalogInput>(channel, NullDeleter<AnalogInput>())) {}
+
+AnalogGyro::AnalogGyro(std::shared_ptr<AnalogInput> channel)
+ : m_analog(channel) {
+ if (channel == nullptr) {
+ wpi_setWPIError(NullParameter);
+ } else {
+ InitGyro();
+ Calibrate();
+ }
+}
+
+AnalogGyro::AnalogGyro(int channel, int center, double offset)
+ : AnalogGyro(std::make_shared<AnalogInput>(channel), center, offset) {
+ AddChild(m_analog);
+}
+
+AnalogGyro::AnalogGyro(std::shared_ptr<AnalogInput> channel, int center,
+ double offset)
+ : m_analog(channel) {
+ if (channel == nullptr) {
+ wpi_setWPIError(NullParameter);
+ } else {
+ InitGyro();
+ int32_t status = 0;
+ HAL_SetAnalogGyroParameters(m_gyroHandle, kDefaultVoltsPerDegreePerSecond,
+ offset, center, &status);
+ if (status != 0) {
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ m_gyroHandle = HAL_kInvalidHandle;
+ return;
+ }
+ Reset();
+ }
+}
+
+AnalogGyro::~AnalogGyro() { HAL_FreeAnalogGyro(m_gyroHandle); }
+
+AnalogGyro::AnalogGyro(AnalogGyro&& rhs)
+ : GyroBase(std::move(rhs)), m_analog(std::move(rhs.m_analog)) {
+ std::swap(m_gyroHandle, rhs.m_gyroHandle);
+}
+
+AnalogGyro& AnalogGyro::operator=(AnalogGyro&& rhs) {
+ GyroBase::operator=(std::move(rhs));
+
+ m_analog = std::move(rhs.m_analog);
+ std::swap(m_gyroHandle, rhs.m_gyroHandle);
+
+ return *this;
+}
+
+double AnalogGyro::GetAngle() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double value = HAL_GetAnalogGyroAngle(m_gyroHandle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+double AnalogGyro::GetRate() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double value = HAL_GetAnalogGyroRate(m_gyroHandle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+int AnalogGyro::GetCenter() const {
+ if (StatusIsFatal()) return 0;
+ int32_t status = 0;
+ int value = HAL_GetAnalogGyroCenter(m_gyroHandle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+double AnalogGyro::GetOffset() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double value = HAL_GetAnalogGyroOffset(m_gyroHandle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+void AnalogGyro::SetSensitivity(double voltsPerDegreePerSecond) {
+ int32_t status = 0;
+ HAL_SetAnalogGyroVoltsPerDegreePerSecond(m_gyroHandle,
+ voltsPerDegreePerSecond, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void AnalogGyro::SetDeadband(double volts) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetAnalogGyroDeadband(m_gyroHandle, volts, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void AnalogGyro::Reset() {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_ResetAnalogGyro(m_gyroHandle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void AnalogGyro::InitGyro() {
+ if (StatusIsFatal()) return;
+ if (m_gyroHandle == HAL_kInvalidHandle) {
+ int32_t status = 0;
+ m_gyroHandle = HAL_InitializeAnalogGyro(m_analog->m_port, &status);
+ if (status == PARAMETER_OUT_OF_RANGE) {
+ wpi_setWPIErrorWithContext(ParameterOutOfRange,
+ " channel (must be accumulator channel)");
+ m_analog = nullptr;
+ m_gyroHandle = HAL_kInvalidHandle;
+ return;
+ }
+ if (status != 0) {
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ m_analog = nullptr;
+ m_gyroHandle = HAL_kInvalidHandle;
+ return;
+ }
+ }
+
+ int32_t status = 0;
+ HAL_SetupAnalogGyro(m_gyroHandle, &status);
+ if (status != 0) {
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ m_analog = nullptr;
+ m_gyroHandle = HAL_kInvalidHandle;
+ return;
+ }
+
+ HAL_Report(HALUsageReporting::kResourceType_Gyro, m_analog->GetChannel());
+ SetName("AnalogGyro", m_analog->GetChannel());
+}
+
+void AnalogGyro::Calibrate() {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_CalibrateAnalogGyro(m_gyroHandle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
diff --git a/wpilibc/src/main/native/cpp/AnalogInput.cpp b/wpilibc/src/main/native/cpp/AnalogInput.cpp
new file mode 100644
index 0000000..52a55d3
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/AnalogInput.cpp
@@ -0,0 +1,250 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/AnalogInput.h"
+
+#include <utility>
+
+#include <hal/AnalogAccumulator.h>
+#include <hal/AnalogInput.h>
+#include <hal/HAL.h>
+#include <hal/Ports.h>
+
+#include "frc/SensorUtil.h"
+#include "frc/Timer.h"
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+AnalogInput::AnalogInput(int channel) {
+ if (!SensorUtil::CheckAnalogInputChannel(channel)) {
+ wpi_setWPIErrorWithContext(ChannelIndexOutOfRange,
+ "Analog Input " + wpi::Twine(channel));
+ return;
+ }
+
+ m_channel = channel;
+
+ HAL_PortHandle port = HAL_GetPort(channel);
+ int32_t status = 0;
+ m_port = HAL_InitializeAnalogInputPort(port, &status);
+ if (status != 0) {
+ wpi_setErrorWithContextRange(status, 0, HAL_GetNumAnalogInputs(), channel,
+ HAL_GetErrorMessage(status));
+ m_channel = std::numeric_limits<int>::max();
+ m_port = HAL_kInvalidHandle;
+ return;
+ }
+
+ HAL_Report(HALUsageReporting::kResourceType_AnalogChannel, channel);
+ SetName("AnalogInput", channel);
+}
+
+AnalogInput::~AnalogInput() { HAL_FreeAnalogInputPort(m_port); }
+
+AnalogInput::AnalogInput(AnalogInput&& rhs)
+ : ErrorBase(std::move(rhs)),
+ SendableBase(std::move(rhs)),
+ PIDSource(std::move(rhs)),
+ m_channel(std::move(rhs.m_channel)),
+ m_accumulatorOffset(std::move(rhs.m_accumulatorOffset)) {
+ std::swap(m_port, rhs.m_port);
+}
+
+AnalogInput& AnalogInput::operator=(AnalogInput&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+ SendableBase::operator=(std::move(rhs));
+ PIDSource::operator=(std::move(rhs));
+
+ m_channel = std::move(rhs.m_channel);
+ std::swap(m_port, rhs.m_port);
+ m_accumulatorOffset = std::move(rhs.m_accumulatorOffset);
+
+ return *this;
+}
+
+int AnalogInput::GetValue() const {
+ if (StatusIsFatal()) return 0;
+ int32_t status = 0;
+ int value = HAL_GetAnalogValue(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+int AnalogInput::GetAverageValue() const {
+ if (StatusIsFatal()) return 0;
+ int32_t status = 0;
+ int value = HAL_GetAnalogAverageValue(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+double AnalogInput::GetVoltage() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double voltage = HAL_GetAnalogVoltage(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return voltage;
+}
+
+double AnalogInput::GetAverageVoltage() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double voltage = HAL_GetAnalogAverageVoltage(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return voltage;
+}
+
+int AnalogInput::GetChannel() const {
+ if (StatusIsFatal()) return 0;
+ return m_channel;
+}
+
+void AnalogInput::SetAverageBits(int bits) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetAnalogAverageBits(m_port, bits, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int AnalogInput::GetAverageBits() const {
+ int32_t status = 0;
+ int averageBits = HAL_GetAnalogAverageBits(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return averageBits;
+}
+
+void AnalogInput::SetOversampleBits(int bits) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetAnalogOversampleBits(m_port, bits, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int AnalogInput::GetOversampleBits() const {
+ if (StatusIsFatal()) return 0;
+ int32_t status = 0;
+ int oversampleBits = HAL_GetAnalogOversampleBits(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return oversampleBits;
+}
+
+int AnalogInput::GetLSBWeight() const {
+ if (StatusIsFatal()) return 0;
+ int32_t status = 0;
+ int lsbWeight = HAL_GetAnalogLSBWeight(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return lsbWeight;
+}
+
+int AnalogInput::GetOffset() const {
+ if (StatusIsFatal()) return 0;
+ int32_t status = 0;
+ int offset = HAL_GetAnalogOffset(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return offset;
+}
+
+bool AnalogInput::IsAccumulatorChannel() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool isAccum = HAL_IsAccumulatorChannel(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return isAccum;
+}
+
+void AnalogInput::InitAccumulator() {
+ if (StatusIsFatal()) return;
+ m_accumulatorOffset = 0;
+ int32_t status = 0;
+ HAL_InitAccumulator(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void AnalogInput::SetAccumulatorInitialValue(int64_t initialValue) {
+ if (StatusIsFatal()) return;
+ m_accumulatorOffset = initialValue;
+}
+
+void AnalogInput::ResetAccumulator() {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_ResetAccumulator(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ if (!StatusIsFatal()) {
+ // Wait until the next sample, so the next call to GetAccumulator*()
+ // won't have old values.
+ const double sampleTime = 1.0 / GetSampleRate();
+ const double overSamples = 1 << GetOversampleBits();
+ const double averageSamples = 1 << GetAverageBits();
+ Wait(sampleTime * overSamples * averageSamples);
+ }
+}
+
+void AnalogInput::SetAccumulatorCenter(int center) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetAccumulatorCenter(m_port, center, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void AnalogInput::SetAccumulatorDeadband(int deadband) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetAccumulatorDeadband(m_port, deadband, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int64_t AnalogInput::GetAccumulatorValue() const {
+ if (StatusIsFatal()) return 0;
+ int32_t status = 0;
+ int64_t value = HAL_GetAccumulatorValue(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value + m_accumulatorOffset;
+}
+
+int64_t AnalogInput::GetAccumulatorCount() const {
+ if (StatusIsFatal()) return 0;
+ int32_t status = 0;
+ int64_t count = HAL_GetAccumulatorCount(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return count;
+}
+
+void AnalogInput::GetAccumulatorOutput(int64_t& value, int64_t& count) const {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_GetAccumulatorOutput(m_port, &value, &count, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ value += m_accumulatorOffset;
+}
+
+void AnalogInput::SetSampleRate(double samplesPerSecond) {
+ int32_t status = 0;
+ HAL_SetAnalogSampleRate(samplesPerSecond, &status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+double AnalogInput::GetSampleRate() {
+ int32_t status = 0;
+ double sampleRate = HAL_GetAnalogSampleRate(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return sampleRate;
+}
+
+double AnalogInput::PIDGet() {
+ if (StatusIsFatal()) return 0.0;
+ return GetAverageVoltage();
+}
+
+void AnalogInput::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Analog Input");
+ builder.AddDoubleProperty("Value", [=]() { return GetAverageVoltage(); },
+ nullptr);
+}
diff --git a/wpilibc/src/main/native/cpp/AnalogOutput.cpp b/wpilibc/src/main/native/cpp/AnalogOutput.cpp
new file mode 100644
index 0000000..b18af5b
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/AnalogOutput.cpp
@@ -0,0 +1,89 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. 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 "frc/AnalogOutput.h"
+
+#include <limits>
+#include <utility>
+
+#include <hal/HAL.h>
+#include <hal/Ports.h>
+
+#include "frc/SensorUtil.h"
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+AnalogOutput::AnalogOutput(int channel) {
+ if (!SensorUtil::CheckAnalogOutputChannel(channel)) {
+ wpi_setWPIErrorWithContext(ChannelIndexOutOfRange,
+ "analog output " + wpi::Twine(channel));
+ m_channel = std::numeric_limits<int>::max();
+ m_port = HAL_kInvalidHandle;
+ return;
+ }
+
+ m_channel = channel;
+
+ HAL_PortHandle port = HAL_GetPort(m_channel);
+ int32_t status = 0;
+ m_port = HAL_InitializeAnalogOutputPort(port, &status);
+ if (status != 0) {
+ wpi_setErrorWithContextRange(status, 0, HAL_GetNumAnalogOutputs(), channel,
+ HAL_GetErrorMessage(status));
+ m_channel = std::numeric_limits<int>::max();
+ m_port = HAL_kInvalidHandle;
+ return;
+ }
+
+ HAL_Report(HALUsageReporting::kResourceType_AnalogOutput, m_channel);
+ SetName("AnalogOutput", m_channel);
+}
+
+AnalogOutput::~AnalogOutput() { HAL_FreeAnalogOutputPort(m_port); }
+
+AnalogOutput::AnalogOutput(AnalogOutput&& rhs)
+ : ErrorBase(std::move(rhs)),
+ SendableBase(std::move(rhs)),
+ m_channel(std::move(rhs.m_channel)) {
+ std::swap(m_port, rhs.m_port);
+}
+
+AnalogOutput& AnalogOutput::operator=(AnalogOutput&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+ SendableBase::operator=(std::move(rhs));
+
+ m_channel = std::move(rhs.m_channel);
+ std::swap(m_port, rhs.m_port);
+
+ return *this;
+}
+
+void AnalogOutput::SetVoltage(double voltage) {
+ int32_t status = 0;
+ HAL_SetAnalogOutput(m_port, voltage, &status);
+
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+double AnalogOutput::GetVoltage() const {
+ int32_t status = 0;
+ double voltage = HAL_GetAnalogOutput(m_port, &status);
+
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ return voltage;
+}
+
+int AnalogOutput::GetChannel() { return m_channel; }
+
+void AnalogOutput::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Analog Output");
+ builder.AddDoubleProperty("Value", [=]() { return GetVoltage(); },
+ [=](double value) { SetVoltage(value); });
+}
diff --git a/wpilibc/src/main/native/cpp/AnalogPotentiometer.cpp b/wpilibc/src/main/native/cpp/AnalogPotentiometer.cpp
new file mode 100644
index 0000000..6c42ff9
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/AnalogPotentiometer.cpp
@@ -0,0 +1,43 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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 "frc/AnalogPotentiometer.h"
+
+#include "frc/RobotController.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+AnalogPotentiometer::AnalogPotentiometer(int channel, double fullRange,
+ double offset)
+ : m_analog_input(std::make_shared<AnalogInput>(channel)),
+ m_fullRange(fullRange),
+ m_offset(offset) {
+ AddChild(m_analog_input);
+}
+
+AnalogPotentiometer::AnalogPotentiometer(AnalogInput* input, double fullRange,
+ double offset)
+ : m_analog_input(input, NullDeleter<AnalogInput>()),
+ m_fullRange(fullRange),
+ m_offset(offset) {}
+
+AnalogPotentiometer::AnalogPotentiometer(std::shared_ptr<AnalogInput> input,
+ double fullRange, double offset)
+ : m_analog_input(input), m_fullRange(fullRange), m_offset(offset) {}
+
+double AnalogPotentiometer::Get() const {
+ return (m_analog_input->GetVoltage() / RobotController::GetVoltage5V()) *
+ m_fullRange +
+ m_offset;
+}
+
+double AnalogPotentiometer::PIDGet() { return Get(); }
+
+void AnalogPotentiometer::InitSendable(SendableBuilder& builder) {
+ m_analog_input->InitSendable(builder);
+}
diff --git a/wpilibc/src/main/native/cpp/AnalogTrigger.cpp b/wpilibc/src/main/native/cpp/AnalogTrigger.cpp
new file mode 100644
index 0000000..aeb58df
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/AnalogTrigger.cpp
@@ -0,0 +1,130 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/AnalogTrigger.h"
+
+#include <utility>
+
+#include <hal/HAL.h>
+
+#include "frc/AnalogInput.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+AnalogTrigger::AnalogTrigger(int channel)
+ : AnalogTrigger(new AnalogInput(channel)) {
+ m_ownsAnalog = true;
+ AddChild(m_analogInput);
+}
+
+AnalogTrigger::AnalogTrigger(AnalogInput* input) {
+ m_analogInput = input;
+ int32_t status = 0;
+ int index = 0;
+ m_trigger = HAL_InitializeAnalogTrigger(input->m_port, &index, &status);
+ if (status != 0) {
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ m_index = std::numeric_limits<int>::max();
+ m_trigger = HAL_kInvalidHandle;
+ return;
+ }
+ m_index = index;
+
+ HAL_Report(HALUsageReporting::kResourceType_AnalogTrigger, input->m_channel);
+ SetName("AnalogTrigger", input->GetChannel());
+}
+
+AnalogTrigger::~AnalogTrigger() {
+ int32_t status = 0;
+ HAL_CleanAnalogTrigger(m_trigger, &status);
+
+ if (m_ownsAnalog) {
+ delete m_analogInput;
+ }
+}
+
+AnalogTrigger::AnalogTrigger(AnalogTrigger&& rhs)
+ : ErrorBase(std::move(rhs)),
+ SendableBase(std::move(rhs)),
+ m_index(std::move(rhs.m_index)) {
+ std::swap(m_trigger, rhs.m_trigger);
+ std::swap(m_analogInput, rhs.m_analogInput);
+ std::swap(m_ownsAnalog, rhs.m_ownsAnalog);
+}
+
+AnalogTrigger& AnalogTrigger::operator=(AnalogTrigger&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+ SendableBase::operator=(std::move(rhs));
+
+ m_index = std::move(rhs.m_index);
+ std::swap(m_trigger, rhs.m_trigger);
+ std::swap(m_analogInput, rhs.m_analogInput);
+ std::swap(m_ownsAnalog, rhs.m_ownsAnalog);
+
+ return *this;
+}
+
+void AnalogTrigger::SetLimitsVoltage(double lower, double upper) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetAnalogTriggerLimitsVoltage(m_trigger, lower, upper, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void AnalogTrigger::SetLimitsRaw(int lower, int upper) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetAnalogTriggerLimitsRaw(m_trigger, lower, upper, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void AnalogTrigger::SetAveraged(bool useAveragedValue) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetAnalogTriggerAveraged(m_trigger, useAveragedValue, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void AnalogTrigger::SetFiltered(bool useFilteredValue) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetAnalogTriggerFiltered(m_trigger, useFilteredValue, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int AnalogTrigger::GetIndex() const {
+ if (StatusIsFatal()) return -1;
+ return m_index;
+}
+
+bool AnalogTrigger::GetInWindow() {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool result = HAL_GetAnalogTriggerInWindow(m_trigger, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return result;
+}
+
+bool AnalogTrigger::GetTriggerState() {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool result = HAL_GetAnalogTriggerTriggerState(m_trigger, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return result;
+}
+
+std::shared_ptr<AnalogTriggerOutput> AnalogTrigger::CreateOutput(
+ AnalogTriggerType type) const {
+ if (StatusIsFatal()) return nullptr;
+ return std::shared_ptr<AnalogTriggerOutput>(
+ new AnalogTriggerOutput(*this, type), NullDeleter<AnalogTriggerOutput>());
+}
+
+void AnalogTrigger::InitSendable(SendableBuilder& builder) {
+ if (m_ownsAnalog) m_analogInput->InitSendable(builder);
+}
diff --git a/wpilibc/src/main/native/cpp/AnalogTriggerOutput.cpp b/wpilibc/src/main/native/cpp/AnalogTriggerOutput.cpp
new file mode 100644
index 0000000..b2a8cd5
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/AnalogTriggerOutput.cpp
@@ -0,0 +1,54 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/AnalogTriggerOutput.h"
+
+#include <hal/HAL.h>
+
+#include "frc/AnalogTrigger.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+AnalogTriggerOutput::~AnalogTriggerOutput() {
+ if (m_interrupt != HAL_kInvalidHandle) {
+ int32_t status = 0;
+ HAL_CleanInterrupts(m_interrupt, &status);
+ // ignore status, as an invalid handle just needs to be ignored.
+ m_interrupt = HAL_kInvalidHandle;
+ }
+}
+
+bool AnalogTriggerOutput::Get() const {
+ int32_t status = 0;
+ bool result = HAL_GetAnalogTriggerOutput(
+ m_trigger.m_trigger, static_cast<HAL_AnalogTriggerType>(m_outputType),
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return result;
+}
+
+HAL_Handle AnalogTriggerOutput::GetPortHandleForRouting() const {
+ return m_trigger.m_trigger;
+}
+
+AnalogTriggerType AnalogTriggerOutput::GetAnalogTriggerTypeForRouting() const {
+ return m_outputType;
+}
+
+bool AnalogTriggerOutput::IsAnalogTrigger() const { return true; }
+
+int AnalogTriggerOutput::GetChannel() const { return m_trigger.m_index; }
+
+void AnalogTriggerOutput::InitSendable(SendableBuilder&) {}
+
+AnalogTriggerOutput::AnalogTriggerOutput(const AnalogTrigger& trigger,
+ AnalogTriggerType outputType)
+ : m_trigger(trigger), m_outputType(outputType) {
+ HAL_Report(HALUsageReporting::kResourceType_AnalogTriggerOutput,
+ trigger.GetIndex(), static_cast<uint8_t>(outputType));
+}
diff --git a/wpilibc/src/main/native/cpp/BuiltInAccelerometer.cpp b/wpilibc/src/main/native/cpp/BuiltInAccelerometer.cpp
new file mode 100644
index 0000000..8452e38
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/BuiltInAccelerometer.cpp
@@ -0,0 +1,48 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. 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 "frc/BuiltInAccelerometer.h"
+
+#include <hal/Accelerometer.h>
+#include <hal/HAL.h>
+
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+BuiltInAccelerometer::BuiltInAccelerometer(Range range) {
+ SetRange(range);
+
+ HAL_Report(HALUsageReporting::kResourceType_Accelerometer, 0, 0,
+ "Built-in accelerometer");
+ SetName("BuiltInAccel", 0);
+}
+
+void BuiltInAccelerometer::SetRange(Range range) {
+ if (range == kRange_16G) {
+ wpi_setWPIErrorWithContext(
+ ParameterOutOfRange, "16G range not supported (use k2G, k4G, or k8G)");
+ }
+
+ HAL_SetAccelerometerActive(false);
+ HAL_SetAccelerometerRange((HAL_AccelerometerRange)range);
+ HAL_SetAccelerometerActive(true);
+}
+
+double BuiltInAccelerometer::GetX() { return HAL_GetAccelerometerX(); }
+
+double BuiltInAccelerometer::GetY() { return HAL_GetAccelerometerY(); }
+
+double BuiltInAccelerometer::GetZ() { return HAL_GetAccelerometerZ(); }
+
+void BuiltInAccelerometer::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("3AxisAccelerometer");
+ builder.AddDoubleProperty("X", [=]() { return GetX(); }, nullptr);
+ builder.AddDoubleProperty("Y", [=]() { return GetY(); }, nullptr);
+ builder.AddDoubleProperty("Z", [=]() { return GetZ(); }, nullptr);
+}
diff --git a/wpilibc/src/main/native/cpp/CAN.cpp b/wpilibc/src/main/native/cpp/CAN.cpp
new file mode 100644
index 0000000..f01eb3f
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/CAN.cpp
@@ -0,0 +1,147 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/CAN.h"
+
+#include <utility>
+
+#include <hal/CAN.h>
+#include <hal/CANAPI.h>
+#include <hal/Errors.h>
+#include <hal/FRCUsageReporting.h>
+#include <hal/HALBase.h>
+
+using namespace frc;
+
+CAN::CAN(int deviceId) {
+ int32_t status = 0;
+ m_handle =
+ HAL_InitializeCAN(kTeamManufacturer, deviceId, kTeamDeviceType, &status);
+ if (status != 0) {
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ m_handle = HAL_kInvalidHandle;
+ return;
+ }
+
+ HAL_Report(HALUsageReporting::kResourceType_CAN, deviceId);
+}
+
+CAN::CAN(int deviceId, int deviceManufacturer, int deviceType) {
+ int32_t status = 0;
+ m_handle = HAL_InitializeCAN(
+ static_cast<HAL_CANManufacturer>(deviceManufacturer), deviceId,
+ static_cast<HAL_CANDeviceType>(deviceType), &status);
+ if (status != 0) {
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ m_handle = HAL_kInvalidHandle;
+ return;
+ }
+
+ HAL_Report(HALUsageReporting::kResourceType_CAN, deviceId);
+}
+
+CAN::~CAN() {
+ if (StatusIsFatal()) return;
+ if (m_handle != HAL_kInvalidHandle) {
+ HAL_CleanCAN(m_handle);
+ m_handle = HAL_kInvalidHandle;
+ }
+}
+
+CAN::CAN(CAN&& rhs) : ErrorBase(std::move(rhs)) {
+ std::swap(m_handle, rhs.m_handle);
+}
+
+CAN& CAN::operator=(CAN&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+
+ std::swap(m_handle, rhs.m_handle);
+
+ return *this;
+}
+
+void CAN::WritePacket(const uint8_t* data, int length, int apiId) {
+ int32_t status = 0;
+ HAL_WriteCANPacket(m_handle, data, length, apiId, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void CAN::WritePacketRepeating(const uint8_t* data, int length, int apiId,
+ int repeatMs) {
+ int32_t status = 0;
+ HAL_WriteCANPacketRepeating(m_handle, data, length, apiId, repeatMs, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void CAN::StopPacketRepeating(int apiId) {
+ int32_t status = 0;
+ HAL_StopCANPacketRepeating(m_handle, apiId, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+bool CAN::ReadPacketNew(int apiId, CANData* data) {
+ int32_t status = 0;
+ HAL_ReadCANPacketNew(m_handle, apiId, data->data, &data->length,
+ &data->timestamp, &status);
+ if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
+ return false;
+ }
+ if (status != 0) {
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool CAN::ReadPacketLatest(int apiId, CANData* data) {
+ int32_t status = 0;
+ HAL_ReadCANPacketLatest(m_handle, apiId, data->data, &data->length,
+ &data->timestamp, &status);
+ if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
+ return false;
+ }
+ if (status != 0) {
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool CAN::ReadPacketTimeout(int apiId, int timeoutMs, CANData* data) {
+ int32_t status = 0;
+ HAL_ReadCANPacketTimeout(m_handle, apiId, data->data, &data->length,
+ &data->timestamp, timeoutMs, &status);
+ if (status == HAL_CAN_TIMEOUT ||
+ status == HAL_ERR_CANSessionMux_MessageNotFound) {
+ return false;
+ }
+ if (status != 0) {
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool CAN::ReadPeriodicPacket(int apiId, int timeoutMs, int periodMs,
+ CANData* data) {
+ int32_t status = 0;
+ HAL_ReadCANPeriodicPacket(m_handle, apiId, data->data, &data->length,
+ &data->timestamp, timeoutMs, periodMs, &status);
+ if (status == HAL_CAN_TIMEOUT ||
+ status == HAL_ERR_CANSessionMux_MessageNotFound) {
+ return false;
+ }
+ if (status != 0) {
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return false;
+ } else {
+ return true;
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/Compressor.cpp b/wpilibc/src/main/native/cpp/Compressor.cpp
new file mode 100644
index 0000000..48e1ed6
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Compressor.cpp
@@ -0,0 +1,218 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. 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 "frc/Compressor.h"
+
+#include <hal/Compressor.h>
+#include <hal/HAL.h>
+#include <hal/Ports.h>
+#include <hal/Solenoid.h>
+
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+Compressor::Compressor(int pcmID) : m_module(pcmID) {
+ int32_t status = 0;
+ m_compressorHandle = HAL_InitializeCompressor(m_module, &status);
+ if (status != 0) {
+ wpi_setErrorWithContextRange(status, 0, HAL_GetNumPCMModules(), pcmID,
+ HAL_GetErrorMessage(status));
+ return;
+ }
+ SetClosedLoopControl(true);
+
+ HAL_Report(HALUsageReporting::kResourceType_Compressor, pcmID);
+ SetName("Compressor", pcmID);
+}
+
+void Compressor::Start() {
+ if (StatusIsFatal()) return;
+ SetClosedLoopControl(true);
+}
+
+void Compressor::Stop() {
+ if (StatusIsFatal()) return;
+ SetClosedLoopControl(false);
+}
+
+bool Compressor::Enabled() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value;
+
+ value = HAL_GetCompressor(m_compressorHandle, &status);
+
+ if (status) {
+ wpi_setWPIError(Timeout);
+ }
+
+ return value;
+}
+
+bool Compressor::GetPressureSwitchValue() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value;
+
+ value = HAL_GetCompressorPressureSwitch(m_compressorHandle, &status);
+
+ if (status) {
+ wpi_setWPIError(Timeout);
+ }
+
+ return value;
+}
+
+double Compressor::GetCompressorCurrent() const {
+ if (StatusIsFatal()) return 0;
+ int32_t status = 0;
+ double value;
+
+ value = HAL_GetCompressorCurrent(m_compressorHandle, &status);
+
+ if (status) {
+ wpi_setWPIError(Timeout);
+ }
+
+ return value;
+}
+
+void Compressor::SetClosedLoopControl(bool on) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+
+ HAL_SetCompressorClosedLoopControl(m_compressorHandle, on, &status);
+
+ if (status) {
+ wpi_setWPIError(Timeout);
+ }
+}
+
+bool Compressor::GetClosedLoopControl() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value;
+
+ value = HAL_GetCompressorClosedLoopControl(m_compressorHandle, &status);
+
+ if (status) {
+ wpi_setWPIError(Timeout);
+ }
+
+ return value;
+}
+
+bool Compressor::GetCompressorCurrentTooHighFault() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value;
+
+ value = HAL_GetCompressorCurrentTooHighFault(m_compressorHandle, &status);
+
+ if (status) {
+ wpi_setWPIError(Timeout);
+ }
+
+ return value;
+}
+
+bool Compressor::GetCompressorCurrentTooHighStickyFault() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value;
+
+ value =
+ HAL_GetCompressorCurrentTooHighStickyFault(m_compressorHandle, &status);
+
+ if (status) {
+ wpi_setWPIError(Timeout);
+ }
+
+ return value;
+}
+
+bool Compressor::GetCompressorShortedStickyFault() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value;
+
+ value = HAL_GetCompressorShortedStickyFault(m_compressorHandle, &status);
+
+ if (status) {
+ wpi_setWPIError(Timeout);
+ }
+
+ return value;
+}
+
+bool Compressor::GetCompressorShortedFault() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value;
+
+ value = HAL_GetCompressorShortedFault(m_compressorHandle, &status);
+
+ if (status) {
+ wpi_setWPIError(Timeout);
+ }
+
+ return value;
+}
+
+bool Compressor::GetCompressorNotConnectedStickyFault() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value;
+
+ value = HAL_GetCompressorNotConnectedStickyFault(m_compressorHandle, &status);
+
+ if (status) {
+ wpi_setWPIError(Timeout);
+ }
+
+ return value;
+}
+
+bool Compressor::GetCompressorNotConnectedFault() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value;
+
+ value = HAL_GetCompressorNotConnectedFault(m_compressorHandle, &status);
+
+ if (status) {
+ wpi_setWPIError(Timeout);
+ }
+
+ return value;
+}
+
+void Compressor::ClearAllPCMStickyFaults() {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+
+ HAL_ClearAllPCMStickyFaults(m_module, &status);
+
+ if (status) {
+ wpi_setWPIError(Timeout);
+ }
+}
+
+void Compressor::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Compressor");
+ builder.AddBooleanProperty("Enabled", [=]() { return Enabled(); },
+ [=](bool value) {
+ if (value)
+ Start();
+ else
+ Stop();
+ });
+ builder.AddBooleanProperty(
+ "Pressure switch", [=]() { return GetPressureSwitchValue(); }, nullptr);
+}
diff --git a/wpilibc/src/main/native/cpp/ControllerPower.cpp b/wpilibc/src/main/native/cpp/ControllerPower.cpp
new file mode 100644
index 0000000..d3012ea
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/ControllerPower.cpp
@@ -0,0 +1,115 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/ControllerPower.h"
+
+#include <stdint.h>
+
+#include <hal/HAL.h>
+#include <hal/Power.h>
+
+#include "frc/ErrorBase.h"
+
+using namespace frc;
+
+double ControllerPower::GetInputVoltage() {
+ int32_t status = 0;
+ double retVal = HAL_GetVinVoltage(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double ControllerPower::GetInputCurrent() {
+ int32_t status = 0;
+ double retVal = HAL_GetVinCurrent(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double ControllerPower::GetVoltage3V3() {
+ int32_t status = 0;
+ double retVal = HAL_GetUserVoltage3V3(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double ControllerPower::GetCurrent3V3() {
+ int32_t status = 0;
+ double retVal = HAL_GetUserCurrent3V3(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+bool ControllerPower::GetEnabled3V3() {
+ int32_t status = 0;
+ bool retVal = HAL_GetUserActive3V3(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+int ControllerPower::GetFaultCount3V3() {
+ int32_t status = 0;
+ int retVal = HAL_GetUserCurrentFaults3V3(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double ControllerPower::GetVoltage5V() {
+ int32_t status = 0;
+ double retVal = HAL_GetUserVoltage5V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double ControllerPower::GetCurrent5V() {
+ int32_t status = 0;
+ double retVal = HAL_GetUserCurrent5V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+bool ControllerPower::GetEnabled5V() {
+ int32_t status = 0;
+ bool retVal = HAL_GetUserActive5V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+int ControllerPower::GetFaultCount5V() {
+ int32_t status = 0;
+ int retVal = HAL_GetUserCurrentFaults5V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double ControllerPower::GetVoltage6V() {
+ int32_t status = 0;
+ double retVal = HAL_GetUserVoltage6V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double ControllerPower::GetCurrent6V() {
+ int32_t status = 0;
+ double retVal = HAL_GetUserCurrent6V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+bool ControllerPower::GetEnabled6V() {
+ int32_t status = 0;
+ bool retVal = HAL_GetUserActive6V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+int ControllerPower::GetFaultCount6V() {
+ int32_t status = 0;
+ int retVal = HAL_GetUserCurrentFaults6V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
diff --git a/wpilibc/src/main/native/cpp/Counter.cpp b/wpilibc/src/main/native/cpp/Counter.cpp
new file mode 100644
index 0000000..c97bbc5
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Counter.cpp
@@ -0,0 +1,358 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Counter.h"
+
+#include <utility>
+
+#include <hal/HAL.h>
+
+#include "frc/AnalogTrigger.h"
+#include "frc/DigitalInput.h"
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+Counter::Counter(Mode mode) {
+ int32_t status = 0;
+ m_counter = HAL_InitializeCounter((HAL_Counter_Mode)mode, &m_index, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ SetMaxPeriod(.5);
+
+ HAL_Report(HALUsageReporting::kResourceType_Counter, m_index, mode);
+ SetName("Counter", m_index);
+}
+
+Counter::Counter(int channel) : Counter(kTwoPulse) {
+ SetUpSource(channel);
+ ClearDownSource();
+}
+
+Counter::Counter(DigitalSource* source) : Counter(kTwoPulse) {
+ SetUpSource(source);
+ ClearDownSource();
+}
+
+Counter::Counter(std::shared_ptr<DigitalSource> source) : Counter(kTwoPulse) {
+ SetUpSource(source);
+ ClearDownSource();
+}
+
+Counter::Counter(const AnalogTrigger& trigger) : Counter(kTwoPulse) {
+ SetUpSource(trigger.CreateOutput(AnalogTriggerType::kState));
+ ClearDownSource();
+}
+
+Counter::Counter(EncodingType encodingType, DigitalSource* upSource,
+ DigitalSource* downSource, bool inverted)
+ : Counter(encodingType,
+ std::shared_ptr<DigitalSource>(upSource,
+ NullDeleter<DigitalSource>()),
+ std::shared_ptr<DigitalSource>(downSource,
+ NullDeleter<DigitalSource>()),
+ inverted) {}
+
+Counter::Counter(EncodingType encodingType,
+ std::shared_ptr<DigitalSource> upSource,
+ std::shared_ptr<DigitalSource> downSource, bool inverted)
+ : Counter(kExternalDirection) {
+ if (encodingType != k1X && encodingType != k2X) {
+ wpi_setWPIErrorWithContext(
+ ParameterOutOfRange,
+ "Counter only supports 1X and 2X quadrature decoding.");
+ return;
+ }
+ SetUpSource(upSource);
+ SetDownSource(downSource);
+ int32_t status = 0;
+
+ if (encodingType == k1X) {
+ SetUpSourceEdge(true, false);
+ HAL_SetCounterAverageSize(m_counter, 1, &status);
+ } else {
+ SetUpSourceEdge(true, true);
+ HAL_SetCounterAverageSize(m_counter, 2, &status);
+ }
+
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ SetDownSourceEdge(inverted, true);
+}
+
+Counter::~Counter() {
+ SetUpdateWhenEmpty(true);
+
+ int32_t status = 0;
+ HAL_FreeCounter(m_counter, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ m_counter = HAL_kInvalidHandle;
+}
+
+Counter::Counter(Counter&& rhs)
+ : ErrorBase(std::move(rhs)),
+ SendableBase(std::move(rhs)),
+ CounterBase(std::move(rhs)),
+ m_upSource(std::move(rhs.m_upSource)),
+ m_downSource(std::move(rhs.m_downSource)),
+ m_index(std::move(rhs.m_index)) {
+ std::swap(m_counter, rhs.m_counter);
+}
+
+Counter& Counter::operator=(Counter&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+ SendableBase::operator=(std::move(rhs));
+ CounterBase::operator=(std::move(rhs));
+
+ m_upSource = std::move(rhs.m_upSource);
+ m_downSource = std::move(rhs.m_downSource);
+ std::swap(m_counter, rhs.m_counter);
+ m_index = std::move(rhs.m_index);
+
+ return *this;
+}
+
+void Counter::SetUpSource(int channel) {
+ if (StatusIsFatal()) return;
+ SetUpSource(std::make_shared<DigitalInput>(channel));
+ AddChild(m_upSource);
+}
+
+void Counter::SetUpSource(AnalogTrigger* analogTrigger,
+ AnalogTriggerType triggerType) {
+ SetUpSource(std::shared_ptr<AnalogTrigger>(analogTrigger,
+ NullDeleter<AnalogTrigger>()),
+ triggerType);
+}
+
+void Counter::SetUpSource(std::shared_ptr<AnalogTrigger> analogTrigger,
+ AnalogTriggerType triggerType) {
+ if (StatusIsFatal()) return;
+ SetUpSource(analogTrigger->CreateOutput(triggerType));
+}
+
+void Counter::SetUpSource(DigitalSource* source) {
+ SetUpSource(
+ std::shared_ptr<DigitalSource>(source, NullDeleter<DigitalSource>()));
+}
+
+void Counter::SetUpSource(std::shared_ptr<DigitalSource> source) {
+ if (StatusIsFatal()) return;
+ m_upSource = source;
+ if (m_upSource->StatusIsFatal()) {
+ CloneError(*m_upSource);
+ } else {
+ int32_t status = 0;
+ HAL_SetCounterUpSource(
+ m_counter, source->GetPortHandleForRouting(),
+ (HAL_AnalogTriggerType)source->GetAnalogTriggerTypeForRouting(),
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ }
+}
+
+void Counter::SetUpSource(DigitalSource& source) {
+ SetUpSource(
+ std::shared_ptr<DigitalSource>(&source, NullDeleter<DigitalSource>()));
+}
+
+void Counter::SetUpSourceEdge(bool risingEdge, bool fallingEdge) {
+ if (StatusIsFatal()) return;
+ if (m_upSource == nullptr) {
+ wpi_setWPIErrorWithContext(
+ NullParameter,
+ "Must set non-nullptr UpSource before setting UpSourceEdge");
+ }
+ int32_t status = 0;
+ HAL_SetCounterUpSourceEdge(m_counter, risingEdge, fallingEdge, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Counter::ClearUpSource() {
+ if (StatusIsFatal()) return;
+ m_upSource.reset();
+ int32_t status = 0;
+ HAL_ClearCounterUpSource(m_counter, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Counter::SetDownSource(int channel) {
+ if (StatusIsFatal()) return;
+ SetDownSource(std::make_shared<DigitalInput>(channel));
+ AddChild(m_downSource);
+}
+
+void Counter::SetDownSource(AnalogTrigger* analogTrigger,
+ AnalogTriggerType triggerType) {
+ SetDownSource(std::shared_ptr<AnalogTrigger>(analogTrigger,
+ NullDeleter<AnalogTrigger>()),
+ triggerType);
+}
+
+void Counter::SetDownSource(std::shared_ptr<AnalogTrigger> analogTrigger,
+ AnalogTriggerType triggerType) {
+ if (StatusIsFatal()) return;
+ SetDownSource(analogTrigger->CreateOutput(triggerType));
+}
+
+void Counter::SetDownSource(DigitalSource* source) {
+ SetDownSource(
+ std::shared_ptr<DigitalSource>(source, NullDeleter<DigitalSource>()));
+}
+
+void Counter::SetDownSource(DigitalSource& source) {
+ SetDownSource(
+ std::shared_ptr<DigitalSource>(&source, NullDeleter<DigitalSource>()));
+}
+
+void Counter::SetDownSource(std::shared_ptr<DigitalSource> source) {
+ if (StatusIsFatal()) return;
+ m_downSource = source;
+ if (m_downSource->StatusIsFatal()) {
+ CloneError(*m_downSource);
+ } else {
+ int32_t status = 0;
+ HAL_SetCounterDownSource(
+ m_counter, source->GetPortHandleForRouting(),
+ (HAL_AnalogTriggerType)source->GetAnalogTriggerTypeForRouting(),
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ }
+}
+
+void Counter::SetDownSourceEdge(bool risingEdge, bool fallingEdge) {
+ if (StatusIsFatal()) return;
+ if (m_downSource == nullptr) {
+ wpi_setWPIErrorWithContext(
+ NullParameter,
+ "Must set non-nullptr DownSource before setting DownSourceEdge");
+ }
+ int32_t status = 0;
+ HAL_SetCounterDownSourceEdge(m_counter, risingEdge, fallingEdge, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Counter::ClearDownSource() {
+ if (StatusIsFatal()) return;
+ m_downSource.reset();
+ int32_t status = 0;
+ HAL_ClearCounterDownSource(m_counter, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Counter::SetUpDownCounterMode() {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetCounterUpDownMode(m_counter, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Counter::SetExternalDirectionMode() {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetCounterExternalDirectionMode(m_counter, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Counter::SetSemiPeriodMode(bool highSemiPeriod) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetCounterSemiPeriodMode(m_counter, highSemiPeriod, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Counter::SetPulseLengthMode(double threshold) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetCounterPulseLengthMode(m_counter, threshold, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Counter::SetReverseDirection(bool reverseDirection) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetCounterReverseDirection(m_counter, reverseDirection, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Counter::SetSamplesToAverage(int samplesToAverage) {
+ if (samplesToAverage < 1 || samplesToAverage > 127) {
+ wpi_setWPIErrorWithContext(
+ ParameterOutOfRange,
+ "Average counter values must be between 1 and 127");
+ }
+ int32_t status = 0;
+ HAL_SetCounterSamplesToAverage(m_counter, samplesToAverage, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int Counter::GetSamplesToAverage() const {
+ int32_t status = 0;
+ int samples = HAL_GetCounterSamplesToAverage(m_counter, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return samples;
+}
+
+int Counter::GetFPGAIndex() const { return m_index; }
+
+int Counter::Get() const {
+ if (StatusIsFatal()) return 0;
+ int32_t status = 0;
+ int value = HAL_GetCounter(m_counter, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+void Counter::Reset() {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_ResetCounter(m_counter, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+double Counter::GetPeriod() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double value = HAL_GetCounterPeriod(m_counter, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+void Counter::SetMaxPeriod(double maxPeriod) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetCounterMaxPeriod(m_counter, maxPeriod, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Counter::SetUpdateWhenEmpty(bool enabled) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetCounterUpdateWhenEmpty(m_counter, enabled, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+bool Counter::GetStopped() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value = HAL_GetCounterStopped(m_counter, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+bool Counter::GetDirection() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value = HAL_GetCounterDirection(m_counter, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+void Counter::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Counter");
+ builder.AddDoubleProperty("Value", [=]() { return Get(); }, nullptr);
+}
diff --git a/wpilibc/src/main/native/cpp/DMC60.cpp b/wpilibc/src/main/native/cpp/DMC60.cpp
new file mode 100644
index 0000000..7dc2d8d
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/DMC60.cpp
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/DMC60.h"
+
+#include <hal/HAL.h>
+
+using namespace frc;
+
+DMC60::DMC60(int channel) : PWMSpeedController(channel) {
+ /*
+ * Note that the DMC 60 uses the following bounds for PWM values. These
+ * values should work reasonably well for most controllers, but if users
+ * experience issues such as asymmetric behavior around the deadband or
+ * inability to saturate the controller in either direction, calibration is
+ * recommended. The calibration procedure can be found in the DMC 60 User
+ * Manual available from Digilent.
+ *
+ * 2.004ms = full "forward"
+ * 1.52ms = the "high end" of the deadband range
+ * 1.50ms = center of the deadband range (off)
+ * 1.48ms = the "low end" of the deadband range
+ * 0.997ms = full "reverse"
+ */
+ SetBounds(2.004, 1.52, 1.50, 1.48, .997);
+ SetPeriodMultiplier(kPeriodMultiplier_1X);
+ SetSpeed(0.0);
+ SetZeroLatch();
+
+ HAL_Report(HALUsageReporting::kResourceType_DigilentDMC60, GetChannel());
+ SetName("DMC60", GetChannel());
+}
diff --git a/wpilibc/src/main/native/cpp/DigitalGlitchFilter.cpp b/wpilibc/src/main/native/cpp/DigitalGlitchFilter.cpp
new file mode 100644
index 0000000..71211b3
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/DigitalGlitchFilter.cpp
@@ -0,0 +1,162 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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 "frc/DigitalGlitchFilter.h"
+
+#include <algorithm>
+#include <array>
+#include <utility>
+
+#include <hal/Constants.h>
+#include <hal/DIO.h>
+#include <hal/HAL.h>
+
+#include "frc/Counter.h"
+#include "frc/Encoder.h"
+#include "frc/SensorUtil.h"
+#include "frc/Utility.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+std::array<bool, 3> DigitalGlitchFilter::m_filterAllocated = {
+ {false, false, false}};
+wpi::mutex DigitalGlitchFilter::m_mutex;
+
+DigitalGlitchFilter::DigitalGlitchFilter() {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ auto index =
+ std::find(m_filterAllocated.begin(), m_filterAllocated.end(), false);
+ wpi_assert(index != m_filterAllocated.end());
+
+ m_channelIndex = std::distance(m_filterAllocated.begin(), index);
+ *index = true;
+
+ HAL_Report(HALUsageReporting::kResourceType_DigitalGlitchFilter,
+ m_channelIndex);
+ SetName("DigitalGlitchFilter", m_channelIndex);
+}
+
+DigitalGlitchFilter::~DigitalGlitchFilter() {
+ if (m_channelIndex >= 0) {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ m_filterAllocated[m_channelIndex] = false;
+ }
+}
+
+DigitalGlitchFilter::DigitalGlitchFilter(DigitalGlitchFilter&& rhs)
+ : ErrorBase(std::move(rhs)), SendableBase(std::move(rhs)) {
+ std::swap(m_channelIndex, rhs.m_channelIndex);
+}
+
+DigitalGlitchFilter& DigitalGlitchFilter::operator=(DigitalGlitchFilter&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+ SendableBase::operator=(std::move(rhs));
+
+ std::swap(m_channelIndex, rhs.m_channelIndex);
+
+ return *this;
+}
+
+void DigitalGlitchFilter::Add(DigitalSource* input) {
+ DoAdd(input, m_channelIndex + 1);
+}
+
+void DigitalGlitchFilter::DoAdd(DigitalSource* input, int requestedIndex) {
+ // Some sources from Counters and Encoders are null. By pushing the check
+ // here, we catch the issue more generally.
+ if (input) {
+ // We don't support GlitchFilters on AnalogTriggers.
+ if (input->IsAnalogTrigger()) {
+ wpi_setErrorWithContext(
+ -1, "Analog Triggers not supported for DigitalGlitchFilters");
+ return;
+ }
+ int32_t status = 0;
+ HAL_SetFilterSelect(input->GetPortHandleForRouting(), requestedIndex,
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ // Validate that we set it correctly.
+ int actualIndex =
+ HAL_GetFilterSelect(input->GetPortHandleForRouting(), &status);
+ wpi_assertEqual(actualIndex, requestedIndex);
+
+ HAL_Report(HALUsageReporting::kResourceType_DigitalInput,
+ input->GetChannel());
+ }
+}
+
+void DigitalGlitchFilter::Add(Encoder* input) {
+ Add(input->m_aSource.get());
+ if (StatusIsFatal()) {
+ return;
+ }
+ Add(input->m_bSource.get());
+}
+
+void DigitalGlitchFilter::Add(Counter* input) {
+ Add(input->m_upSource.get());
+ if (StatusIsFatal()) {
+ return;
+ }
+ Add(input->m_downSource.get());
+}
+
+void DigitalGlitchFilter::Remove(DigitalSource* input) { DoAdd(input, 0); }
+
+void DigitalGlitchFilter::Remove(Encoder* input) {
+ Remove(input->m_aSource.get());
+ if (StatusIsFatal()) {
+ return;
+ }
+ Remove(input->m_bSource.get());
+}
+
+void DigitalGlitchFilter::Remove(Counter* input) {
+ Remove(input->m_upSource.get());
+ if (StatusIsFatal()) {
+ return;
+ }
+ Remove(input->m_downSource.get());
+}
+
+void DigitalGlitchFilter::SetPeriodCycles(int fpgaCycles) {
+ int32_t status = 0;
+ HAL_SetFilterPeriod(m_channelIndex, fpgaCycles, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void DigitalGlitchFilter::SetPeriodNanoSeconds(uint64_t nanoseconds) {
+ int32_t status = 0;
+ int fpgaCycles =
+ nanoseconds * HAL_GetSystemClockTicksPerMicrosecond() / 4 / 1000;
+ HAL_SetFilterPeriod(m_channelIndex, fpgaCycles, &status);
+
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int DigitalGlitchFilter::GetPeriodCycles() {
+ int32_t status = 0;
+ int fpgaCycles = HAL_GetFilterPeriod(m_channelIndex, &status);
+
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ return fpgaCycles;
+}
+
+uint64_t DigitalGlitchFilter::GetPeriodNanoSeconds() {
+ int32_t status = 0;
+ int fpgaCycles = HAL_GetFilterPeriod(m_channelIndex, &status);
+
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ return static_cast<uint64_t>(fpgaCycles) * 1000L /
+ static_cast<uint64_t>(HAL_GetSystemClockTicksPerMicrosecond() / 4);
+}
+
+void DigitalGlitchFilter::InitSendable(SendableBuilder&) {}
diff --git a/wpilibc/src/main/native/cpp/DigitalInput.cpp b/wpilibc/src/main/native/cpp/DigitalInput.cpp
new file mode 100644
index 0000000..273e9b6
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/DigitalInput.cpp
@@ -0,0 +1,93 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/DigitalInput.h"
+
+#include <limits>
+#include <utility>
+
+#include <hal/DIO.h>
+#include <hal/HAL.h>
+#include <hal/Ports.h>
+
+#include "frc/SensorUtil.h"
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+DigitalInput::DigitalInput(int channel) {
+ if (!SensorUtil::CheckDigitalChannel(channel)) {
+ wpi_setWPIErrorWithContext(ChannelIndexOutOfRange,
+ "Digital Channel " + wpi::Twine(channel));
+ m_channel = std::numeric_limits<int>::max();
+ return;
+ }
+ m_channel = channel;
+
+ int32_t status = 0;
+ m_handle = HAL_InitializeDIOPort(HAL_GetPort(channel), true, &status);
+ if (status != 0) {
+ wpi_setErrorWithContextRange(status, 0, HAL_GetNumDigitalChannels(),
+ channel, HAL_GetErrorMessage(status));
+ m_handle = HAL_kInvalidHandle;
+ m_channel = std::numeric_limits<int>::max();
+ return;
+ }
+
+ HAL_Report(HALUsageReporting::kResourceType_DigitalInput, channel);
+ SetName("DigitalInput", channel);
+}
+
+DigitalInput::~DigitalInput() {
+ if (StatusIsFatal()) return;
+ if (m_interrupt != HAL_kInvalidHandle) {
+ int32_t status = 0;
+ HAL_CleanInterrupts(m_interrupt, &status);
+ // Ignore status, as an invalid handle just needs to be ignored.
+ m_interrupt = HAL_kInvalidHandle;
+ }
+
+ HAL_FreeDIOPort(m_handle);
+}
+
+DigitalInput::DigitalInput(DigitalInput&& rhs)
+ : DigitalSource(std::move(rhs)), m_channel(std::move(rhs.m_channel)) {
+ std::swap(m_handle, rhs.m_handle);
+}
+
+DigitalInput& DigitalInput::operator=(DigitalInput&& rhs) {
+ DigitalSource::operator=(std::move(rhs));
+
+ m_channel = std::move(rhs.m_channel);
+ std::swap(m_handle, rhs.m_handle);
+
+ return *this;
+}
+
+bool DigitalInput::Get() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value = HAL_GetDIO(m_handle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+HAL_Handle DigitalInput::GetPortHandleForRouting() const { return m_handle; }
+
+AnalogTriggerType DigitalInput::GetAnalogTriggerTypeForRouting() const {
+ return (AnalogTriggerType)0;
+}
+
+bool DigitalInput::IsAnalogTrigger() const { return false; }
+
+int DigitalInput::GetChannel() const { return m_channel; }
+
+void DigitalInput::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Digital Input");
+ builder.AddBooleanProperty("Value", [=]() { return Get(); }, nullptr);
+}
diff --git a/wpilibc/src/main/native/cpp/DigitalOutput.cpp b/wpilibc/src/main/native/cpp/DigitalOutput.cpp
new file mode 100644
index 0000000..b05c6b1
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/DigitalOutput.cpp
@@ -0,0 +1,165 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/DigitalOutput.h"
+
+#include <limits>
+#include <utility>
+
+#include <hal/DIO.h>
+#include <hal/HAL.h>
+#include <hal/Ports.h>
+
+#include "frc/SensorUtil.h"
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+DigitalOutput::DigitalOutput(int channel) {
+ m_pwmGenerator = HAL_kInvalidHandle;
+ if (!SensorUtil::CheckDigitalChannel(channel)) {
+ wpi_setWPIErrorWithContext(ChannelIndexOutOfRange,
+ "Digital Channel " + wpi::Twine(channel));
+ m_channel = std::numeric_limits<int>::max();
+ return;
+ }
+ m_channel = channel;
+
+ int32_t status = 0;
+ m_handle = HAL_InitializeDIOPort(HAL_GetPort(channel), false, &status);
+ if (status != 0) {
+ wpi_setErrorWithContextRange(status, 0, HAL_GetNumDigitalChannels(),
+ channel, HAL_GetErrorMessage(status));
+ m_channel = std::numeric_limits<int>::max();
+ m_handle = HAL_kInvalidHandle;
+ return;
+ }
+
+ HAL_Report(HALUsageReporting::kResourceType_DigitalOutput, channel);
+ SetName("DigitalOutput", channel);
+}
+
+DigitalOutput::~DigitalOutput() {
+ if (StatusIsFatal()) return;
+ // Disable the PWM in case it was running.
+ DisablePWM();
+
+ HAL_FreeDIOPort(m_handle);
+}
+
+DigitalOutput::DigitalOutput(DigitalOutput&& rhs)
+ : ErrorBase(std::move(rhs)),
+ SendableBase(std::move(rhs)),
+ m_channel(std::move(rhs.m_channel)),
+ m_pwmGenerator(std::move(rhs.m_pwmGenerator)) {
+ std::swap(m_handle, rhs.m_handle);
+}
+
+DigitalOutput& DigitalOutput::operator=(DigitalOutput&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+ SendableBase::operator=(std::move(rhs));
+
+ m_channel = std::move(rhs.m_channel);
+ std::swap(m_handle, rhs.m_handle);
+ m_pwmGenerator = std::move(rhs.m_pwmGenerator);
+
+ return *this;
+}
+
+void DigitalOutput::Set(bool value) {
+ if (StatusIsFatal()) return;
+
+ int32_t status = 0;
+ HAL_SetDIO(m_handle, value, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+bool DigitalOutput::Get() const {
+ if (StatusIsFatal()) return false;
+
+ int32_t status = 0;
+ bool val = HAL_GetDIO(m_handle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return val;
+}
+
+int DigitalOutput::GetChannel() const { return m_channel; }
+
+void DigitalOutput::Pulse(double length) {
+ if (StatusIsFatal()) return;
+
+ int32_t status = 0;
+ HAL_Pulse(m_handle, length, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+bool DigitalOutput::IsPulsing() const {
+ if (StatusIsFatal()) return false;
+
+ int32_t status = 0;
+ bool value = HAL_IsPulsing(m_handle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+void DigitalOutput::SetPWMRate(double rate) {
+ if (StatusIsFatal()) return;
+
+ int32_t status = 0;
+ HAL_SetDigitalPWMRate(rate, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void DigitalOutput::EnablePWM(double initialDutyCycle) {
+ if (m_pwmGenerator != HAL_kInvalidHandle) return;
+
+ int32_t status = 0;
+
+ if (StatusIsFatal()) return;
+ m_pwmGenerator = HAL_AllocateDigitalPWM(&status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ if (StatusIsFatal()) return;
+ HAL_SetDigitalPWMDutyCycle(m_pwmGenerator, initialDutyCycle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ if (StatusIsFatal()) return;
+ HAL_SetDigitalPWMOutputChannel(m_pwmGenerator, m_channel, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void DigitalOutput::DisablePWM() {
+ if (StatusIsFatal()) return;
+ if (m_pwmGenerator == HAL_kInvalidHandle) return;
+
+ int32_t status = 0;
+
+ // Disable the output by routing to a dead bit.
+ HAL_SetDigitalPWMOutputChannel(m_pwmGenerator, SensorUtil::kDigitalChannels,
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ HAL_FreeDigitalPWM(m_pwmGenerator, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ m_pwmGenerator = HAL_kInvalidHandle;
+}
+
+void DigitalOutput::UpdateDutyCycle(double dutyCycle) {
+ if (StatusIsFatal()) return;
+
+ int32_t status = 0;
+ HAL_SetDigitalPWMDutyCycle(m_pwmGenerator, dutyCycle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void DigitalOutput::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Digital Output");
+ builder.AddBooleanProperty("Value", [=]() { return Get(); },
+ [=](bool value) { Set(value); });
+}
diff --git a/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp b/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp
new file mode 100644
index 0000000..86678aa
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp
@@ -0,0 +1,186 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/DoubleSolenoid.h"
+
+#include <utility>
+
+#include <hal/HAL.h>
+#include <hal/Ports.h>
+#include <hal/Solenoid.h>
+
+#include "frc/SensorUtil.h"
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+DoubleSolenoid::DoubleSolenoid(int forwardChannel, int reverseChannel)
+ : DoubleSolenoid(SensorUtil::GetDefaultSolenoidModule(), forwardChannel,
+ reverseChannel) {}
+
+DoubleSolenoid::DoubleSolenoid(int moduleNumber, int forwardChannel,
+ int reverseChannel)
+ : SolenoidBase(moduleNumber),
+ m_forwardChannel(forwardChannel),
+ m_reverseChannel(reverseChannel) {
+ if (!SensorUtil::CheckSolenoidModule(m_moduleNumber)) {
+ wpi_setWPIErrorWithContext(ModuleIndexOutOfRange,
+ "Solenoid Module " + wpi::Twine(m_moduleNumber));
+ return;
+ }
+ if (!SensorUtil::CheckSolenoidChannel(m_forwardChannel)) {
+ wpi_setWPIErrorWithContext(
+ ChannelIndexOutOfRange,
+ "Solenoid Channel " + wpi::Twine(m_forwardChannel));
+ return;
+ }
+ if (!SensorUtil::CheckSolenoidChannel(m_reverseChannel)) {
+ wpi_setWPIErrorWithContext(
+ ChannelIndexOutOfRange,
+ "Solenoid Channel " + wpi::Twine(m_reverseChannel));
+ return;
+ }
+ int32_t status = 0;
+ m_forwardHandle = HAL_InitializeSolenoidPort(
+ HAL_GetPortWithModule(moduleNumber, m_forwardChannel), &status);
+ if (status != 0) {
+ wpi_setErrorWithContextRange(status, 0, HAL_GetNumSolenoidChannels(),
+ forwardChannel, HAL_GetErrorMessage(status));
+ m_forwardHandle = HAL_kInvalidHandle;
+ m_reverseHandle = HAL_kInvalidHandle;
+ return;
+ }
+
+ m_reverseHandle = HAL_InitializeSolenoidPort(
+ HAL_GetPortWithModule(moduleNumber, m_reverseChannel), &status);
+ if (status != 0) {
+ wpi_setErrorWithContextRange(status, 0, HAL_GetNumSolenoidChannels(),
+ reverseChannel, HAL_GetErrorMessage(status));
+ // free forward solenoid
+ HAL_FreeSolenoidPort(m_forwardHandle);
+ m_forwardHandle = HAL_kInvalidHandle;
+ m_reverseHandle = HAL_kInvalidHandle;
+ return;
+ }
+
+ m_forwardMask = 1 << m_forwardChannel;
+ m_reverseMask = 1 << m_reverseChannel;
+
+ HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_forwardChannel,
+ m_moduleNumber);
+ HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_reverseChannel,
+ m_moduleNumber);
+ SetName("DoubleSolenoid", m_moduleNumber, m_forwardChannel);
+}
+
+DoubleSolenoid::~DoubleSolenoid() {
+ HAL_FreeSolenoidPort(m_forwardHandle);
+ HAL_FreeSolenoidPort(m_reverseHandle);
+}
+
+DoubleSolenoid::DoubleSolenoid(DoubleSolenoid&& rhs)
+ : SolenoidBase(std::move(rhs)),
+ m_forwardChannel(std::move(rhs.m_forwardChannel)),
+ m_reverseChannel(std::move(rhs.m_reverseChannel)),
+ m_forwardMask(std::move(rhs.m_forwardMask)),
+ m_reverseMask(std::move(rhs.m_reverseMask)) {
+ std::swap(m_forwardHandle, rhs.m_forwardHandle);
+ std::swap(m_reverseHandle, rhs.m_reverseHandle);
+}
+
+DoubleSolenoid& DoubleSolenoid::operator=(DoubleSolenoid&& rhs) {
+ SolenoidBase::operator=(std::move(rhs));
+
+ m_forwardChannel = std::move(rhs.m_forwardChannel);
+ m_reverseChannel = std::move(rhs.m_reverseChannel);
+ m_forwardMask = std::move(rhs.m_forwardMask);
+ m_reverseMask = std::move(rhs.m_reverseMask);
+ std::swap(m_forwardHandle, rhs.m_forwardHandle);
+ std::swap(m_reverseHandle, rhs.m_reverseHandle);
+
+ return *this;
+}
+
+void DoubleSolenoid::Set(Value value) {
+ if (StatusIsFatal()) return;
+
+ bool forward = false;
+ bool reverse = false;
+ switch (value) {
+ case kOff:
+ forward = false;
+ reverse = false;
+ break;
+ case kForward:
+ forward = true;
+ reverse = false;
+ break;
+ case kReverse:
+ forward = false;
+ reverse = true;
+ break;
+ }
+ int fstatus = 0;
+ HAL_SetSolenoid(m_forwardHandle, forward, &fstatus);
+ int rstatus = 0;
+ HAL_SetSolenoid(m_reverseHandle, reverse, &rstatus);
+
+ wpi_setErrorWithContext(fstatus, HAL_GetErrorMessage(fstatus));
+ wpi_setErrorWithContext(rstatus, HAL_GetErrorMessage(rstatus));
+}
+
+DoubleSolenoid::Value DoubleSolenoid::Get() const {
+ if (StatusIsFatal()) return kOff;
+ int fstatus = 0;
+ int rstatus = 0;
+ bool valueForward = HAL_GetSolenoid(m_forwardHandle, &fstatus);
+ bool valueReverse = HAL_GetSolenoid(m_reverseHandle, &rstatus);
+
+ wpi_setErrorWithContext(fstatus, HAL_GetErrorMessage(fstatus));
+ wpi_setErrorWithContext(rstatus, HAL_GetErrorMessage(rstatus));
+
+ if (valueForward) return kForward;
+ if (valueReverse) return kReverse;
+ return kOff;
+}
+
+bool DoubleSolenoid::IsFwdSolenoidBlackListed() const {
+ int blackList = GetPCMSolenoidBlackList(m_moduleNumber);
+ return (blackList & m_forwardMask) != 0;
+}
+
+bool DoubleSolenoid::IsRevSolenoidBlackListed() const {
+ int blackList = GetPCMSolenoidBlackList(m_moduleNumber);
+ return (blackList & m_reverseMask) != 0;
+}
+
+void DoubleSolenoid::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Double Solenoid");
+ builder.SetActuator(true);
+ builder.SetSafeState([=]() { Set(kOff); });
+ builder.AddSmallStringProperty(
+ "Value",
+ [=](wpi::SmallVectorImpl<char>& buf) -> wpi::StringRef {
+ switch (Get()) {
+ case kForward:
+ return "Forward";
+ case kReverse:
+ return "Reverse";
+ default:
+ return "Off";
+ }
+ },
+ [=](wpi::StringRef value) {
+ Value lvalue = kOff;
+ if (value == "Forward")
+ lvalue = kForward;
+ else if (value == "Reverse")
+ lvalue = kReverse;
+ Set(lvalue);
+ });
+}
diff --git a/wpilibc/src/main/native/cpp/DriverStation.cpp b/wpilibc/src/main/native/cpp/DriverStation.cpp
new file mode 100644
index 0000000..3c274c6
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/DriverStation.cpp
@@ -0,0 +1,621 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/DriverStation.h"
+
+#include <chrono>
+
+#include <hal/HAL.h>
+#include <hal/Power.h>
+#include <hal/cpp/Log.h>
+#include <networktables/NetworkTable.h>
+#include <networktables/NetworkTableEntry.h>
+#include <networktables/NetworkTableInstance.h>
+#include <wpi/SmallString.h>
+#include <wpi/StringRef.h>
+
+#include "frc/AnalogInput.h"
+#include "frc/MotorSafety.h"
+#include "frc/Timer.h"
+#include "frc/Utility.h"
+#include "frc/WPIErrors.h"
+
+namespace frc {
+
+class MatchDataSender {
+ public:
+ std::shared_ptr<nt::NetworkTable> table;
+ nt::NetworkTableEntry typeMetadata;
+ nt::NetworkTableEntry gameSpecificMessage;
+ nt::NetworkTableEntry eventName;
+ nt::NetworkTableEntry matchNumber;
+ nt::NetworkTableEntry replayNumber;
+ nt::NetworkTableEntry matchType;
+ nt::NetworkTableEntry alliance;
+ nt::NetworkTableEntry station;
+ nt::NetworkTableEntry controlWord;
+
+ MatchDataSender() {
+ table = nt::NetworkTableInstance::GetDefault().GetTable("FMSInfo");
+ typeMetadata = table->GetEntry(".type");
+ typeMetadata.ForceSetString("FMSInfo");
+ gameSpecificMessage = table->GetEntry("GameSpecificMessage");
+ gameSpecificMessage.ForceSetString("");
+ eventName = table->GetEntry("EventName");
+ eventName.ForceSetString("");
+ matchNumber = table->GetEntry("MatchNumber");
+ matchNumber.ForceSetDouble(0);
+ replayNumber = table->GetEntry("ReplayNumber");
+ replayNumber.ForceSetDouble(0);
+ matchType = table->GetEntry("MatchType");
+ matchType.ForceSetDouble(0);
+ alliance = table->GetEntry("IsRedAlliance");
+ alliance.ForceSetBoolean(true);
+ station = table->GetEntry("StationNumber");
+ station.ForceSetDouble(1);
+ controlWord = table->GetEntry("FMSControlData");
+ controlWord.ForceSetDouble(0);
+ }
+};
+} // namespace frc
+
+using namespace frc;
+
+static constexpr double kJoystickUnpluggedMessageInterval = 1.0;
+
+DriverStation::~DriverStation() {
+ m_isRunning = false;
+ // Trigger a DS mutex release in case there is no driver station running.
+ HAL_ReleaseDSMutex();
+ m_dsThread.join();
+}
+
+DriverStation& DriverStation::GetInstance() {
+ static DriverStation instance;
+ return instance;
+}
+
+void DriverStation::ReportError(const wpi::Twine& error) {
+ wpi::SmallString<128> temp;
+ HAL_SendError(1, 1, 0, error.toNullTerminatedStringRef(temp).data(), "", "",
+ 1);
+}
+
+void DriverStation::ReportWarning(const wpi::Twine& error) {
+ wpi::SmallString<128> temp;
+ HAL_SendError(0, 1, 0, error.toNullTerminatedStringRef(temp).data(), "", "",
+ 1);
+}
+
+void DriverStation::ReportError(bool isError, int32_t code,
+ const wpi::Twine& error,
+ const wpi::Twine& location,
+ const wpi::Twine& stack) {
+ wpi::SmallString<128> errorTemp;
+ wpi::SmallString<128> locationTemp;
+ wpi::SmallString<128> stackTemp;
+ HAL_SendError(isError, code, 0,
+ error.toNullTerminatedStringRef(errorTemp).data(),
+ location.toNullTerminatedStringRef(locationTemp).data(),
+ stack.toNullTerminatedStringRef(stackTemp).data(), 1);
+}
+
+bool DriverStation::GetStickButton(int stick, int button) {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ return false;
+ }
+ if (button <= 0) {
+ ReportJoystickUnpluggedError(
+ "ERROR: Button indexes begin at 1 in WPILib for C++ and Java");
+ return false;
+ }
+
+ HAL_JoystickButtons buttons;
+ HAL_GetJoystickButtons(stick, &buttons);
+
+ if (button > buttons.count) {
+ ReportJoystickUnpluggedWarning(
+ "Joystick Button missing, check if all controllers are plugged in");
+ return false;
+ }
+
+ return buttons.buttons & 1 << (button - 1);
+}
+
+bool DriverStation::GetStickButtonPressed(int stick, int button) {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ return false;
+ }
+ if (button <= 0) {
+ ReportJoystickUnpluggedError(
+ "ERROR: Button indexes begin at 1 in WPILib for C++ and Java");
+ return false;
+ }
+
+ HAL_JoystickButtons buttons;
+ HAL_GetJoystickButtons(stick, &buttons);
+
+ if (button > buttons.count) {
+ ReportJoystickUnpluggedWarning(
+ "Joystick Button missing, check if all controllers are plugged in");
+ return false;
+ }
+ std::unique_lock<wpi::mutex> lock(m_buttonEdgeMutex);
+ // If button was pressed, clear flag and return true
+ if (m_joystickButtonsPressed[stick] & 1 << (button - 1)) {
+ m_joystickButtonsPressed[stick] &= ~(1 << (button - 1));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool DriverStation::GetStickButtonReleased(int stick, int button) {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ return false;
+ }
+ if (button <= 0) {
+ ReportJoystickUnpluggedError(
+ "ERROR: Button indexes begin at 1 in WPILib for C++ and Java");
+ return false;
+ }
+
+ HAL_JoystickButtons buttons;
+ HAL_GetJoystickButtons(stick, &buttons);
+
+ if (button > buttons.count) {
+ ReportJoystickUnpluggedWarning(
+ "Joystick Button missing, check if all controllers are plugged in");
+ return false;
+ }
+ std::unique_lock<wpi::mutex> lock(m_buttonEdgeMutex);
+ // If button was released, clear flag and return true
+ if (m_joystickButtonsReleased[stick] & 1 << (button - 1)) {
+ m_joystickButtonsReleased[stick] &= ~(1 << (button - 1));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+double DriverStation::GetStickAxis(int stick, int axis) {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ return 0.0;
+ }
+ if (axis < 0 || axis >= HAL_kMaxJoystickAxes) {
+ wpi_setWPIError(BadJoystickAxis);
+ return 0.0;
+ }
+
+ HAL_JoystickAxes axes;
+ HAL_GetJoystickAxes(stick, &axes);
+
+ if (axis >= axes.count) {
+ ReportJoystickUnpluggedWarning(
+ "Joystick Axis missing, check if all controllers are plugged in");
+ return 0.0;
+ }
+
+ return axes.axes[axis];
+}
+
+int DriverStation::GetStickPOV(int stick, int pov) {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ return -1;
+ }
+ if (pov < 0 || pov >= HAL_kMaxJoystickPOVs) {
+ wpi_setWPIError(BadJoystickAxis);
+ return -1;
+ }
+
+ HAL_JoystickPOVs povs;
+ HAL_GetJoystickPOVs(stick, &povs);
+
+ if (pov >= povs.count) {
+ ReportJoystickUnpluggedWarning(
+ "Joystick POV missing, check if all controllers are plugged in");
+ return -1;
+ }
+
+ return povs.povs[pov];
+}
+
+int DriverStation::GetStickButtons(int stick) const {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ return 0;
+ }
+
+ HAL_JoystickButtons buttons;
+ HAL_GetJoystickButtons(stick, &buttons);
+
+ return buttons.buttons;
+}
+
+int DriverStation::GetStickAxisCount(int stick) const {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ return 0;
+ }
+
+ HAL_JoystickAxes axes;
+ HAL_GetJoystickAxes(stick, &axes);
+
+ return axes.count;
+}
+
+int DriverStation::GetStickPOVCount(int stick) const {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ return 0;
+ }
+
+ HAL_JoystickPOVs povs;
+ HAL_GetJoystickPOVs(stick, &povs);
+
+ return povs.count;
+}
+
+int DriverStation::GetStickButtonCount(int stick) const {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ return 0;
+ }
+
+ HAL_JoystickButtons buttons;
+ HAL_GetJoystickButtons(stick, &buttons);
+
+ return buttons.count;
+}
+
+bool DriverStation::GetJoystickIsXbox(int stick) const {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ return false;
+ }
+
+ HAL_JoystickDescriptor descriptor;
+ HAL_GetJoystickDescriptor(stick, &descriptor);
+
+ return static_cast<bool>(descriptor.isXbox);
+}
+
+int DriverStation::GetJoystickType(int stick) const {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ return -1;
+ }
+
+ HAL_JoystickDescriptor descriptor;
+ HAL_GetJoystickDescriptor(stick, &descriptor);
+
+ return static_cast<int>(descriptor.type);
+}
+
+std::string DriverStation::GetJoystickName(int stick) const {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ }
+
+ HAL_JoystickDescriptor descriptor;
+ HAL_GetJoystickDescriptor(stick, &descriptor);
+
+ return descriptor.name;
+}
+
+int DriverStation::GetJoystickAxisType(int stick, int axis) const {
+ if (stick < 0 || stick >= kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ return -1;
+ }
+
+ HAL_JoystickDescriptor descriptor;
+ HAL_GetJoystickDescriptor(stick, &descriptor);
+
+ return static_cast<bool>(descriptor.axisTypes);
+}
+
+bool DriverStation::IsEnabled() const {
+ HAL_ControlWord controlWord;
+ HAL_GetControlWord(&controlWord);
+ return controlWord.enabled && controlWord.dsAttached;
+}
+
+bool DriverStation::IsDisabled() const {
+ HAL_ControlWord controlWord;
+ HAL_GetControlWord(&controlWord);
+ return !(controlWord.enabled && controlWord.dsAttached);
+}
+
+bool DriverStation::IsAutonomous() const {
+ HAL_ControlWord controlWord;
+ HAL_GetControlWord(&controlWord);
+ return controlWord.autonomous;
+}
+
+bool DriverStation::IsOperatorControl() const {
+ HAL_ControlWord controlWord;
+ HAL_GetControlWord(&controlWord);
+ return !(controlWord.autonomous || controlWord.test);
+}
+
+bool DriverStation::IsTest() const {
+ HAL_ControlWord controlWord;
+ HAL_GetControlWord(&controlWord);
+ return controlWord.test;
+}
+
+bool DriverStation::IsDSAttached() const {
+ HAL_ControlWord controlWord;
+ HAL_GetControlWord(&controlWord);
+ return controlWord.dsAttached;
+}
+
+bool DriverStation::IsNewControlData() const { return HAL_IsNewControlData(); }
+
+bool DriverStation::IsFMSAttached() const {
+ HAL_ControlWord controlWord;
+ HAL_GetControlWord(&controlWord);
+ return controlWord.fmsAttached;
+}
+
+bool DriverStation::IsSysActive() const {
+ int32_t status = 0;
+ bool retVal = HAL_GetSystemActive(&status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+bool DriverStation::IsBrownedOut() const {
+ int32_t status = 0;
+ bool retVal = HAL_GetBrownedOut(&status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+std::string DriverStation::GetGameSpecificMessage() const {
+ HAL_MatchInfo info;
+ HAL_GetMatchInfo(&info);
+ return std::string(reinterpret_cast<char*>(info.gameSpecificMessage),
+ info.gameSpecificMessageSize);
+}
+
+std::string DriverStation::GetEventName() const {
+ HAL_MatchInfo info;
+ HAL_GetMatchInfo(&info);
+ return info.eventName;
+}
+
+DriverStation::MatchType DriverStation::GetMatchType() const {
+ HAL_MatchInfo info;
+ HAL_GetMatchInfo(&info);
+ return static_cast<DriverStation::MatchType>(info.matchType);
+}
+
+int DriverStation::GetMatchNumber() const {
+ HAL_MatchInfo info;
+ HAL_GetMatchInfo(&info);
+ return info.matchNumber;
+}
+
+int DriverStation::GetReplayNumber() const {
+ HAL_MatchInfo info;
+ HAL_GetMatchInfo(&info);
+ return info.replayNumber;
+}
+
+DriverStation::Alliance DriverStation::GetAlliance() const {
+ int32_t status = 0;
+ auto allianceStationID = HAL_GetAllianceStation(&status);
+ switch (allianceStationID) {
+ case HAL_AllianceStationID_kRed1:
+ case HAL_AllianceStationID_kRed2:
+ case HAL_AllianceStationID_kRed3:
+ return kRed;
+ case HAL_AllianceStationID_kBlue1:
+ case HAL_AllianceStationID_kBlue2:
+ case HAL_AllianceStationID_kBlue3:
+ return kBlue;
+ default:
+ return kInvalid;
+ }
+}
+
+int DriverStation::GetLocation() const {
+ int32_t status = 0;
+ auto allianceStationID = HAL_GetAllianceStation(&status);
+ switch (allianceStationID) {
+ case HAL_AllianceStationID_kRed1:
+ case HAL_AllianceStationID_kBlue1:
+ return 1;
+ case HAL_AllianceStationID_kRed2:
+ case HAL_AllianceStationID_kBlue2:
+ return 2;
+ case HAL_AllianceStationID_kRed3:
+ case HAL_AllianceStationID_kBlue3:
+ return 3;
+ default:
+ return 0;
+ }
+}
+
+void DriverStation::WaitForData() { WaitForData(0); }
+
+bool DriverStation::WaitForData(double timeout) {
+ auto timeoutTime =
+ std::chrono::steady_clock::now() + std::chrono::duration<double>(timeout);
+
+ std::unique_lock<wpi::mutex> lock(m_waitForDataMutex);
+ int currentCount = m_waitForDataCounter;
+ while (m_waitForDataCounter == currentCount) {
+ if (timeout > 0) {
+ auto timedOut = m_waitForDataCond.wait_until(lock, timeoutTime);
+ if (timedOut == std::cv_status::timeout) {
+ return false;
+ }
+ } else {
+ m_waitForDataCond.wait(lock);
+ }
+ }
+ return true;
+}
+
+double DriverStation::GetMatchTime() const {
+ int32_t status;
+ return HAL_GetMatchTime(&status);
+}
+
+double DriverStation::GetBatteryVoltage() const {
+ int32_t status = 0;
+ double voltage = HAL_GetVinVoltage(&status);
+ wpi_setErrorWithContext(status, "getVinVoltage");
+
+ return voltage;
+}
+
+void DriverStation::GetData() {
+ {
+ // Compute the pressed and released buttons
+ HAL_JoystickButtons currentButtons;
+ std::unique_lock<wpi::mutex> lock(m_buttonEdgeMutex);
+
+ for (int32_t i = 0; i < kJoystickPorts; i++) {
+ HAL_GetJoystickButtons(i, ¤tButtons);
+
+ // If buttons weren't pressed and are now, set flags in m_buttonsPressed
+ m_joystickButtonsPressed[i] |=
+ ~m_previousButtonStates[i].buttons & currentButtons.buttons;
+
+ // If buttons were pressed and aren't now, set flags in m_buttonsReleased
+ m_joystickButtonsReleased[i] |=
+ m_previousButtonStates[i].buttons & ~currentButtons.buttons;
+
+ m_previousButtonStates[i] = currentButtons;
+ }
+ }
+
+ {
+ std::lock_guard<wpi::mutex> waitLock(m_waitForDataMutex);
+ // Nofify all threads
+ m_waitForDataCounter++;
+ m_waitForDataCond.notify_all();
+ }
+
+ SendMatchData();
+}
+
+DriverStation::DriverStation() {
+ HAL_Initialize(500, 0);
+ m_waitForDataCounter = 0;
+
+ m_matchDataSender = std::make_unique<MatchDataSender>();
+
+ // All joysticks should default to having zero axes, povs and buttons, so
+ // uninitialized memory doesn't get sent to speed controllers.
+ for (unsigned int i = 0; i < kJoystickPorts; i++) {
+ m_joystickButtonsPressed[i] = 0;
+ m_joystickButtonsReleased[i] = 0;
+ m_previousButtonStates[i].count = 0;
+ m_previousButtonStates[i].buttons = 0;
+ }
+
+ m_dsThread = std::thread(&DriverStation::Run, this);
+}
+
+void DriverStation::ReportJoystickUnpluggedError(const wpi::Twine& message) {
+ double currentTime = Timer::GetFPGATimestamp();
+ if (currentTime > m_nextMessageTime) {
+ ReportError(message);
+ m_nextMessageTime = currentTime + kJoystickUnpluggedMessageInterval;
+ }
+}
+
+void DriverStation::ReportJoystickUnpluggedWarning(const wpi::Twine& message) {
+ double currentTime = Timer::GetFPGATimestamp();
+ if (currentTime > m_nextMessageTime) {
+ ReportWarning(message);
+ m_nextMessageTime = currentTime + kJoystickUnpluggedMessageInterval;
+ }
+}
+
+void DriverStation::Run() {
+ m_isRunning = true;
+ int safetyCounter = 0;
+ while (m_isRunning) {
+ HAL_WaitForDSData();
+ GetData();
+
+ if (IsDisabled()) safetyCounter = 0;
+
+ if (++safetyCounter >= 4) {
+ MotorSafety::CheckMotors();
+ safetyCounter = 0;
+ }
+ if (m_userInDisabled) HAL_ObserveUserProgramDisabled();
+ if (m_userInAutonomous) HAL_ObserveUserProgramAutonomous();
+ if (m_userInTeleop) HAL_ObserveUserProgramTeleop();
+ if (m_userInTest) HAL_ObserveUserProgramTest();
+ }
+}
+
+void DriverStation::SendMatchData() {
+ int32_t status = 0;
+ HAL_AllianceStationID alliance = HAL_GetAllianceStation(&status);
+ bool isRedAlliance = false;
+ int stationNumber = 1;
+ switch (alliance) {
+ case HAL_AllianceStationID::HAL_AllianceStationID_kBlue1:
+ isRedAlliance = false;
+ stationNumber = 1;
+ break;
+ case HAL_AllianceStationID::HAL_AllianceStationID_kBlue2:
+ isRedAlliance = false;
+ stationNumber = 2;
+ break;
+ case HAL_AllianceStationID::HAL_AllianceStationID_kBlue3:
+ isRedAlliance = false;
+ stationNumber = 3;
+ break;
+ case HAL_AllianceStationID::HAL_AllianceStationID_kRed1:
+ isRedAlliance = true;
+ stationNumber = 1;
+ break;
+ case HAL_AllianceStationID::HAL_AllianceStationID_kRed2:
+ isRedAlliance = true;
+ stationNumber = 2;
+ break;
+ default:
+ isRedAlliance = true;
+ stationNumber = 3;
+ break;
+ }
+
+ HAL_MatchInfo tmpDataStore;
+ HAL_GetMatchInfo(&tmpDataStore);
+
+ m_matchDataSender->alliance.SetBoolean(isRedAlliance);
+ m_matchDataSender->station.SetDouble(stationNumber);
+ m_matchDataSender->eventName.SetString(tmpDataStore.eventName);
+ m_matchDataSender->gameSpecificMessage.SetString(
+ std::string(reinterpret_cast<char*>(tmpDataStore.gameSpecificMessage),
+ tmpDataStore.gameSpecificMessageSize));
+ m_matchDataSender->matchNumber.SetDouble(tmpDataStore.matchNumber);
+ m_matchDataSender->replayNumber.SetDouble(tmpDataStore.replayNumber);
+ m_matchDataSender->matchType.SetDouble(
+ static_cast<int>(tmpDataStore.matchType));
+
+ HAL_ControlWord ctlWord;
+ HAL_GetControlWord(&ctlWord);
+ int32_t wordInt = 0;
+ std::memcpy(&wordInt, &ctlWord, sizeof(wordInt));
+ m_matchDataSender->controlWord.SetDouble(wordInt);
+}
diff --git a/wpilibc/src/main/native/cpp/Encoder.cpp b/wpilibc/src/main/native/cpp/Encoder.cpp
new file mode 100644
index 0000000..77e7a2a
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Encoder.cpp
@@ -0,0 +1,287 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Encoder.h"
+
+#include <utility>
+
+#include <hal/Encoder.h>
+#include <hal/FRCUsageReporting.h>
+#include <hal/HALBase.h>
+
+#include "frc/DigitalInput.h"
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+Encoder::Encoder(int aChannel, int bChannel, bool reverseDirection,
+ EncodingType encodingType) {
+ m_aSource = std::make_shared<DigitalInput>(aChannel);
+ m_bSource = std::make_shared<DigitalInput>(bChannel);
+ InitEncoder(reverseDirection, encodingType);
+ AddChild(m_aSource);
+ AddChild(m_bSource);
+}
+
+Encoder::Encoder(DigitalSource* aSource, DigitalSource* bSource,
+ bool reverseDirection, EncodingType encodingType)
+ : m_aSource(aSource, NullDeleter<DigitalSource>()),
+ m_bSource(bSource, NullDeleter<DigitalSource>()) {
+ if (m_aSource == nullptr || m_bSource == nullptr)
+ wpi_setWPIError(NullParameter);
+ else
+ InitEncoder(reverseDirection, encodingType);
+}
+
+Encoder::Encoder(DigitalSource& aSource, DigitalSource& bSource,
+ bool reverseDirection, EncodingType encodingType)
+ : m_aSource(&aSource, NullDeleter<DigitalSource>()),
+ m_bSource(&bSource, NullDeleter<DigitalSource>()) {
+ InitEncoder(reverseDirection, encodingType);
+}
+
+Encoder::Encoder(std::shared_ptr<DigitalSource> aSource,
+ std::shared_ptr<DigitalSource> bSource, bool reverseDirection,
+ EncodingType encodingType)
+ : m_aSource(aSource), m_bSource(bSource) {
+ if (m_aSource == nullptr || m_bSource == nullptr)
+ wpi_setWPIError(NullParameter);
+ else
+ InitEncoder(reverseDirection, encodingType);
+}
+
+Encoder::~Encoder() {
+ int32_t status = 0;
+ HAL_FreeEncoder(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+Encoder::Encoder(Encoder&& rhs)
+ : ErrorBase(std::move(rhs)),
+ SendableBase(std::move(rhs)),
+ CounterBase(std::move(rhs)),
+ PIDSource(std::move(rhs)),
+ m_aSource(std::move(rhs.m_aSource)),
+ m_bSource(std::move(rhs.m_bSource)),
+ m_indexSource(std::move(rhs.m_indexSource)) {
+ std::swap(m_encoder, rhs.m_encoder);
+}
+
+Encoder& Encoder::operator=(Encoder&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+ SendableBase::operator=(std::move(rhs));
+ CounterBase::operator=(std::move(rhs));
+ PIDSource::operator=(std::move(rhs));
+
+ m_aSource = std::move(rhs.m_aSource);
+ m_bSource = std::move(rhs.m_bSource);
+ m_indexSource = std::move(rhs.m_indexSource);
+ std::swap(m_encoder, rhs.m_encoder);
+
+ return *this;
+}
+
+int Encoder::Get() const {
+ if (StatusIsFatal()) return 0;
+ int32_t status = 0;
+ int value = HAL_GetEncoder(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+void Encoder::Reset() {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_ResetEncoder(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+double Encoder::GetPeriod() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double value = HAL_GetEncoderPeriod(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+void Encoder::SetMaxPeriod(double maxPeriod) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetEncoderMaxPeriod(m_encoder, maxPeriod, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+bool Encoder::GetStopped() const {
+ if (StatusIsFatal()) return true;
+ int32_t status = 0;
+ bool value = HAL_GetEncoderStopped(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+bool Encoder::GetDirection() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value = HAL_GetEncoderDirection(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+int Encoder::GetRaw() const {
+ if (StatusIsFatal()) return 0;
+ int32_t status = 0;
+ int value = HAL_GetEncoderRaw(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+int Encoder::GetEncodingScale() const {
+ int32_t status = 0;
+ int val = HAL_GetEncoderEncodingScale(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return val;
+}
+
+double Encoder::GetDistance() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double value = HAL_GetEncoderDistance(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+double Encoder::GetRate() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double value = HAL_GetEncoderRate(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+void Encoder::SetMinRate(double minRate) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetEncoderMinRate(m_encoder, minRate, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Encoder::SetDistancePerPulse(double distancePerPulse) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetEncoderDistancePerPulse(m_encoder, distancePerPulse, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+double Encoder::GetDistancePerPulse() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double distancePerPulse = HAL_GetEncoderDistancePerPulse(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return distancePerPulse;
+}
+
+void Encoder::SetReverseDirection(bool reverseDirection) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetEncoderReverseDirection(m_encoder, reverseDirection, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Encoder::SetSamplesToAverage(int samplesToAverage) {
+ if (samplesToAverage < 1 || samplesToAverage > 127) {
+ wpi_setWPIErrorWithContext(
+ ParameterOutOfRange,
+ "Average counter values must be between 1 and 127");
+ return;
+ }
+ int32_t status = 0;
+ HAL_SetEncoderSamplesToAverage(m_encoder, samplesToAverage, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int Encoder::GetSamplesToAverage() const {
+ int32_t status = 0;
+ int result = HAL_GetEncoderSamplesToAverage(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return result;
+}
+
+double Encoder::PIDGet() {
+ if (StatusIsFatal()) return 0.0;
+ switch (GetPIDSourceType()) {
+ case PIDSourceType::kDisplacement:
+ return GetDistance();
+ case PIDSourceType::kRate:
+ return GetRate();
+ default:
+ return 0.0;
+ }
+}
+
+void Encoder::SetIndexSource(int channel, Encoder::IndexingType type) {
+ // Force digital input if just given an index
+ m_indexSource = std::make_shared<DigitalInput>(channel);
+ AddChild(m_indexSource);
+ SetIndexSource(*m_indexSource.get(), type);
+}
+
+void Encoder::SetIndexSource(const DigitalSource& source,
+ Encoder::IndexingType type) {
+ int32_t status = 0;
+ HAL_SetEncoderIndexSource(
+ m_encoder, source.GetPortHandleForRouting(),
+ (HAL_AnalogTriggerType)source.GetAnalogTriggerTypeForRouting(),
+ (HAL_EncoderIndexingType)type, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int Encoder::GetFPGAIndex() const {
+ int32_t status = 0;
+ int val = HAL_GetEncoderFPGAIndex(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return val;
+}
+
+void Encoder::InitSendable(SendableBuilder& builder) {
+ int32_t status = 0;
+ HAL_EncoderEncodingType type = HAL_GetEncoderEncodingType(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ if (type == HAL_EncoderEncodingType::HAL_Encoder_k4X)
+ builder.SetSmartDashboardType("Quadrature Encoder");
+ else
+ builder.SetSmartDashboardType("Encoder");
+
+ builder.AddDoubleProperty("Speed", [=]() { return GetRate(); }, nullptr);
+ builder.AddDoubleProperty("Distance", [=]() { return GetDistance(); },
+ nullptr);
+ builder.AddDoubleProperty("Distance per Tick",
+ [=]() { return GetDistancePerPulse(); }, nullptr);
+}
+
+void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType) {
+ int32_t status = 0;
+ m_encoder = HAL_InitializeEncoder(
+ m_aSource->GetPortHandleForRouting(),
+ (HAL_AnalogTriggerType)m_aSource->GetAnalogTriggerTypeForRouting(),
+ m_bSource->GetPortHandleForRouting(),
+ (HAL_AnalogTriggerType)m_bSource->GetAnalogTriggerTypeForRouting(),
+ reverseDirection, (HAL_EncoderEncodingType)encodingType, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ HAL_Report(HALUsageReporting::kResourceType_Encoder, GetFPGAIndex(),
+ encodingType);
+ SetName("Encoder", m_aSource->GetChannel());
+}
+
+double Encoder::DecodingScaleFactor() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double val = HAL_GetEncoderDecodingScaleFactor(m_encoder, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return val;
+}
diff --git a/wpilibc/src/main/native/cpp/Error.cpp b/wpilibc/src/main/native/cpp/Error.cpp
new file mode 100644
index 0000000..f758032
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Error.cpp
@@ -0,0 +1,98 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Error.h"
+
+#include <wpi/Path.h>
+
+#include "frc/DriverStation.h"
+#include "frc/Timer.h"
+#include "frc/Utility.h"
+
+using namespace frc;
+
+Error::Error(Code code, const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function, int lineNumber,
+ const ErrorBase* originatingObject) {
+ Set(code, contextMessage, filename, function, lineNumber, originatingObject);
+}
+
+bool Error::operator<(const Error& rhs) const {
+ if (m_code < rhs.m_code) {
+ return true;
+ } else if (m_message < rhs.m_message) {
+ return true;
+ } else if (m_filename < rhs.m_filename) {
+ return true;
+ } else if (m_function < rhs.m_function) {
+ return true;
+ } else if (m_lineNumber < rhs.m_lineNumber) {
+ return true;
+ } else if (m_originatingObject < rhs.m_originatingObject) {
+ return true;
+ } else if (m_timestamp < rhs.m_timestamp) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Error::Code Error::GetCode() const { return m_code; }
+
+std::string Error::GetMessage() const { return m_message; }
+
+std::string Error::GetFilename() const { return m_filename; }
+
+std::string Error::GetFunction() const { return m_function; }
+
+int Error::GetLineNumber() const { return m_lineNumber; }
+
+const ErrorBase* Error::GetOriginatingObject() const {
+ return m_originatingObject;
+}
+
+double Error::GetTimestamp() const { return m_timestamp; }
+
+void Error::Set(Code code, const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber, const ErrorBase* originatingObject) {
+ bool report = true;
+
+ if (code == m_code && GetTime() - m_timestamp < 1) {
+ report = false;
+ }
+
+ m_code = code;
+ m_message = contextMessage.str();
+ m_filename = filename;
+ m_function = function;
+ m_lineNumber = lineNumber;
+ m_originatingObject = originatingObject;
+
+ if (report) {
+ m_timestamp = GetTime();
+ Report();
+ }
+}
+
+void Error::Report() {
+ DriverStation::ReportError(
+ true, m_code, m_message,
+ m_function + wpi::Twine(" [") + wpi::sys::path::filename(m_filename) +
+ wpi::Twine(':') + wpi::Twine(m_lineNumber) + wpi::Twine(']'),
+ GetStackTrace(4));
+}
+
+void Error::Clear() {
+ m_code = 0;
+ m_message = "";
+ m_filename = "";
+ m_function = "";
+ m_lineNumber = 0;
+ m_originatingObject = nullptr;
+ m_timestamp = 0.0;
+}
diff --git a/wpilibc/src/main/native/cpp/ErrorBase.cpp b/wpilibc/src/main/native/cpp/ErrorBase.cpp
new file mode 100644
index 0000000..947e53b
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/ErrorBase.cpp
@@ -0,0 +1,152 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/ErrorBase.h"
+
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <set>
+
+#include <hal/HAL.h>
+#include <wpi/Format.h>
+#include <wpi/SmallString.h>
+#include <wpi/raw_ostream.h>
+
+#define WPI_ERRORS_DEFINE_STRINGS
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+static wpi::mutex globalErrorsMutex;
+static std::set<Error> globalErrors;
+
+ErrorBase::ErrorBase() { HAL_Initialize(500, 0); }
+
+Error& ErrorBase::GetError() { return m_error; }
+
+const Error& ErrorBase::GetError() const { return m_error; }
+
+void ErrorBase::ClearError() const { m_error.Clear(); }
+
+void ErrorBase::SetErrnoError(const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber) const {
+ wpi::SmallString<128> buf;
+ wpi::raw_svector_ostream err(buf);
+ int errNo = errno;
+ if (errNo == 0) {
+ err << "OK: ";
+ } else {
+ err << std::strerror(errNo) << " (" << wpi::format_hex(errNo, 10, true)
+ << "): ";
+ }
+
+ // Set the current error information for this object.
+ m_error.Set(-1, err.str() + contextMessage, filename, function, lineNumber,
+ this);
+
+ // Update the global error if there is not one already set.
+ std::lock_guard<wpi::mutex> mutex(globalErrorsMutex);
+ globalErrors.insert(m_error);
+}
+
+void ErrorBase::SetImaqError(int success, const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber) const {
+ // If there was an error
+ if (success <= 0) {
+ // Set the current error information for this object.
+ m_error.Set(success, wpi::Twine(success) + ": " + contextMessage, filename,
+ function, lineNumber, this);
+
+ // Update the global error if there is not one already set.
+ std::lock_guard<wpi::mutex> mutex(globalErrorsMutex);
+ globalErrors.insert(m_error);
+ }
+}
+
+void ErrorBase::SetError(Error::Code code, const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber) const {
+ // If there was an error
+ if (code != 0) {
+ // Set the current error information for this object.
+ m_error.Set(code, contextMessage, filename, function, lineNumber, this);
+
+ // Update the global error if there is not one already set.
+ std::lock_guard<wpi::mutex> mutex(globalErrorsMutex);
+ globalErrors.insert(m_error);
+ }
+}
+
+void ErrorBase::SetErrorRange(Error::Code code, int32_t minRange,
+ int32_t maxRange, int32_t requestedValue,
+ const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber) const {
+ // If there was an error
+ if (code != 0) {
+ // Set the current error information for this object.
+ m_error.Set(code,
+ contextMessage + ", Minimum Value: " + wpi::Twine(minRange) +
+ ", MaximumValue: " + wpi::Twine(maxRange) +
+ ", Requested Value: " + wpi::Twine(requestedValue),
+ filename, function, lineNumber, this);
+
+ // Update the global error if there is not one already set.
+ std::lock_guard<wpi::mutex> mutex(globalErrorsMutex);
+ globalErrors.insert(m_error);
+ }
+}
+
+void ErrorBase::SetWPIError(const wpi::Twine& errorMessage, Error::Code code,
+ const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber) const {
+ // Set the current error information for this object.
+ m_error.Set(code, errorMessage + ": " + contextMessage, filename, function,
+ lineNumber, this);
+
+ // Update the global error if there is not one already set.
+ std::lock_guard<wpi::mutex> mutex(globalErrorsMutex);
+ globalErrors.insert(m_error);
+}
+
+void ErrorBase::CloneError(const ErrorBase& rhs) const {
+ m_error = rhs.GetError();
+}
+
+bool ErrorBase::StatusIsFatal() const { return m_error.GetCode() < 0; }
+
+void ErrorBase::SetGlobalError(Error::Code code,
+ const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber) {
+ // If there was an error
+ if (code != 0) {
+ std::lock_guard<wpi::mutex> mutex(globalErrorsMutex);
+
+ // Set the current error information for this object.
+ globalErrors.emplace(code, contextMessage, filename, function, lineNumber,
+ nullptr);
+ }
+}
+
+void ErrorBase::SetGlobalWPIError(const wpi::Twine& errorMessage,
+ const wpi::Twine& contextMessage,
+ wpi::StringRef filename,
+ wpi::StringRef function, int lineNumber) {
+ std::lock_guard<wpi::mutex> mutex(globalErrorsMutex);
+ globalErrors.emplace(-1, errorMessage + ": " + contextMessage, filename,
+ function, lineNumber, nullptr);
+}
+
+const Error& ErrorBase::GetGlobalError() {
+ std::lock_guard<wpi::mutex> mutex(globalErrorsMutex);
+ return *globalErrors.begin();
+}
diff --git a/wpilibc/src/main/native/cpp/Filesystem.cpp b/wpilibc/src/main/native/cpp/Filesystem.cpp
new file mode 100644
index 0000000..1546050
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Filesystem.cpp
@@ -0,0 +1,31 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/Filesystem.h"
+
+#include <wpi/FileSystem.h>
+#include <wpi/Path.h>
+
+#include "frc/RobotBase.h"
+
+void frc::filesystem::GetLaunchDirectory(wpi::SmallVectorImpl<char>& result) {
+ wpi::sys::fs::current_path(result);
+}
+
+void frc::filesystem::GetOperatingDirectory(
+ wpi::SmallVectorImpl<char>& result) {
+ if (RobotBase::IsReal()) {
+ wpi::sys::path::native("/home/lvuser", result);
+ } else {
+ frc::filesystem::GetLaunchDirectory(result);
+ }
+}
+
+void frc::filesystem::GetDeployDirectory(wpi::SmallVectorImpl<char>& result) {
+ frc::filesystem::GetOperatingDirectory(result);
+ wpi::sys::path::append(result, "deploy");
+}
diff --git a/wpilibc/src/main/native/cpp/GamepadBase.cpp b/wpilibc/src/main/native/cpp/GamepadBase.cpp
new file mode 100644
index 0000000..4eeb744
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/GamepadBase.cpp
@@ -0,0 +1,12 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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 "frc/GamepadBase.h"
+
+using namespace frc;
+
+GamepadBase::GamepadBase(int port) : GenericHID(port) {}
diff --git a/wpilibc/src/main/native/cpp/GearTooth.cpp b/wpilibc/src/main/native/cpp/GearTooth.cpp
new file mode 100644
index 0000000..fba5a24
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/GearTooth.cpp
@@ -0,0 +1,43 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/GearTooth.h"
+
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+constexpr double GearTooth::kGearToothThreshold;
+
+GearTooth::GearTooth(int channel, bool directionSensitive) : Counter(channel) {
+ EnableDirectionSensing(directionSensitive);
+ SetName("GearTooth", channel);
+}
+
+GearTooth::GearTooth(DigitalSource* source, bool directionSensitive)
+ : Counter(source) {
+ EnableDirectionSensing(directionSensitive);
+ SetName("GearTooth", source->GetChannel());
+}
+
+GearTooth::GearTooth(std::shared_ptr<DigitalSource> source,
+ bool directionSensitive)
+ : Counter(source) {
+ EnableDirectionSensing(directionSensitive);
+ SetName("GearTooth", source->GetChannel());
+}
+
+void GearTooth::EnableDirectionSensing(bool directionSensitive) {
+ if (directionSensitive) {
+ SetPulseLengthMode(kGearToothThreshold);
+ }
+}
+
+void GearTooth::InitSendable(SendableBuilder& builder) {
+ Counter::InitSendable(builder);
+ builder.SetSmartDashboardType("Gear Tooth");
+}
diff --git a/wpilibc/src/main/native/cpp/GenericHID.cpp b/wpilibc/src/main/native/cpp/GenericHID.cpp
new file mode 100644
index 0000000..d1a3112
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/GenericHID.cpp
@@ -0,0 +1,85 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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 "frc/GenericHID.h"
+
+#include <hal/HAL.h>
+
+#include "frc/DriverStation.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+GenericHID::GenericHID(int port) : m_ds(DriverStation::GetInstance()) {
+ if (port >= DriverStation::kJoystickPorts) {
+ wpi_setWPIError(BadJoystickIndex);
+ }
+ m_port = port;
+}
+
+bool GenericHID::GetRawButton(int button) const {
+ return m_ds.GetStickButton(m_port, button);
+}
+
+bool GenericHID::GetRawButtonPressed(int button) {
+ return m_ds.GetStickButtonPressed(m_port, button);
+}
+
+bool GenericHID::GetRawButtonReleased(int button) {
+ return m_ds.GetStickButtonReleased(m_port, button);
+}
+
+double GenericHID::GetRawAxis(int axis) const {
+ return m_ds.GetStickAxis(m_port, axis);
+}
+
+int GenericHID::GetPOV(int pov) const { return m_ds.GetStickPOV(m_port, pov); }
+
+int GenericHID::GetAxisCount() const { return m_ds.GetStickAxisCount(m_port); }
+
+int GenericHID::GetPOVCount() const { return m_ds.GetStickPOVCount(m_port); }
+
+int GenericHID::GetButtonCount() const {
+ return m_ds.GetStickButtonCount(m_port);
+}
+
+GenericHID::HIDType GenericHID::GetType() const {
+ return static_cast<HIDType>(m_ds.GetJoystickType(m_port));
+}
+
+std::string GenericHID::GetName() const { return m_ds.GetJoystickName(m_port); }
+
+int GenericHID::GetAxisType(int axis) const {
+ return m_ds.GetJoystickAxisType(m_port, axis);
+}
+
+int GenericHID::GetPort() const { return m_port; }
+
+void GenericHID::SetOutput(int outputNumber, bool value) {
+ m_outputs =
+ (m_outputs & ~(1 << (outputNumber - 1))) | (value << (outputNumber - 1));
+
+ HAL_SetJoystickOutputs(m_port, m_outputs, m_leftRumble, m_rightRumble);
+}
+
+void GenericHID::SetOutputs(int value) {
+ m_outputs = value;
+ HAL_SetJoystickOutputs(m_port, m_outputs, m_leftRumble, m_rightRumble);
+}
+
+void GenericHID::SetRumble(RumbleType type, double value) {
+ if (value < 0)
+ value = 0;
+ else if (value > 1)
+ value = 1;
+ if (type == kLeftRumble) {
+ m_leftRumble = value * 65535;
+ } else {
+ m_rightRumble = value * 65535;
+ }
+ HAL_SetJoystickOutputs(m_port, m_outputs, m_leftRumble, m_rightRumble);
+}
diff --git a/wpilibc/src/main/native/cpp/GyroBase.cpp b/wpilibc/src/main/native/cpp/GyroBase.cpp
new file mode 100644
index 0000000..ec67675
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/GyroBase.cpp
@@ -0,0 +1,29 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/GyroBase.h"
+
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+double GyroBase::PIDGet() {
+ switch (GetPIDSourceType()) {
+ case PIDSourceType::kRate:
+ return GetRate();
+ case PIDSourceType::kDisplacement:
+ return GetAngle();
+ default:
+ return 0;
+ }
+}
+
+void GyroBase::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Gyro");
+ builder.AddDoubleProperty("Value", [=]() { return GetAngle(); }, nullptr);
+}
diff --git a/wpilibc/src/main/native/cpp/I2C.cpp b/wpilibc/src/main/native/cpp/I2C.cpp
new file mode 100644
index 0000000..4b18f73
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/I2C.cpp
@@ -0,0 +1,111 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/I2C.h"
+
+#include <utility>
+
+#include <hal/HAL.h>
+#include <hal/I2C.h>
+
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+I2C::I2C(Port port, int deviceAddress)
+ : m_port(static_cast<HAL_I2CPort>(port)), m_deviceAddress(deviceAddress) {
+ int32_t status = 0;
+ HAL_InitializeI2C(m_port, &status);
+ // wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ HAL_Report(HALUsageReporting::kResourceType_I2C, deviceAddress);
+}
+
+I2C::~I2C() { HAL_CloseI2C(m_port); }
+
+I2C::I2C(I2C&& rhs)
+ : ErrorBase(std::move(rhs)),
+ m_deviceAddress(std::move(rhs.m_deviceAddress)) {
+ std::swap(m_port, rhs.m_port);
+}
+
+I2C& I2C::operator=(I2C&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+
+ std::swap(m_port, rhs.m_port);
+ m_deviceAddress = std::move(rhs.m_deviceAddress);
+
+ return *this;
+}
+
+bool I2C::Transaction(uint8_t* dataToSend, int sendSize, uint8_t* dataReceived,
+ int receiveSize) {
+ int32_t status = 0;
+ status = HAL_TransactionI2C(m_port, m_deviceAddress, dataToSend, sendSize,
+ dataReceived, receiveSize);
+ // wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return status < 0;
+}
+
+bool I2C::AddressOnly() { return Transaction(nullptr, 0, nullptr, 0); }
+
+bool I2C::Write(int registerAddress, uint8_t data) {
+ uint8_t buffer[2];
+ buffer[0] = registerAddress;
+ buffer[1] = data;
+ int32_t status = 0;
+ status = HAL_WriteI2C(m_port, m_deviceAddress, buffer, sizeof(buffer));
+ return status < 0;
+}
+
+bool I2C::WriteBulk(uint8_t* data, int count) {
+ int32_t status = 0;
+ status = HAL_WriteI2C(m_port, m_deviceAddress, data, count);
+ return status < 0;
+}
+
+bool I2C::Read(int registerAddress, int count, uint8_t* buffer) {
+ if (count < 1) {
+ wpi_setWPIErrorWithContext(ParameterOutOfRange, "count");
+ return true;
+ }
+ if (buffer == nullptr) {
+ wpi_setWPIErrorWithContext(NullParameter, "buffer");
+ return true;
+ }
+ uint8_t regAddr = registerAddress;
+ return Transaction(®Addr, sizeof(regAddr), buffer, count);
+}
+
+bool I2C::ReadOnly(int count, uint8_t* buffer) {
+ if (count < 1) {
+ wpi_setWPIErrorWithContext(ParameterOutOfRange, "count");
+ return true;
+ }
+ if (buffer == nullptr) {
+ wpi_setWPIErrorWithContext(NullParameter, "buffer");
+ return true;
+ }
+ return HAL_ReadI2C(m_port, m_deviceAddress, buffer, count) < 0;
+}
+
+bool I2C::VerifySensor(int registerAddress, int count,
+ const uint8_t* expected) {
+ // TODO: Make use of all 7 read bytes
+ uint8_t deviceData[4];
+ for (int i = 0, curRegisterAddress = registerAddress; i < count;
+ i += 4, curRegisterAddress += 4) {
+ int toRead = count - i < 4 ? count - i : 4;
+ // Read the chunk of data. Return false if the sensor does not respond.
+ if (Read(curRegisterAddress, toRead, deviceData)) return false;
+
+ for (int j = 0; j < toRead; j++) {
+ if (deviceData[j] != expected[i + j]) return false;
+ }
+ }
+ return true;
+}
diff --git a/wpilibc/src/main/native/cpp/InterruptableSensorBase.cpp b/wpilibc/src/main/native/cpp/InterruptableSensorBase.cpp
new file mode 100644
index 0000000..220043f
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/InterruptableSensorBase.cpp
@@ -0,0 +1,135 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/InterruptableSensorBase.h"
+
+#include <hal/HAL.h>
+
+#include "frc/Utility.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+void InterruptableSensorBase::RequestInterrupts(
+ HAL_InterruptHandlerFunction handler, void* param) {
+ if (StatusIsFatal()) return;
+
+ wpi_assert(m_interrupt == HAL_kInvalidHandle);
+ AllocateInterrupts(false);
+ if (StatusIsFatal()) return; // if allocate failed, out of interrupts
+
+ int32_t status = 0;
+ HAL_RequestInterrupts(
+ m_interrupt, GetPortHandleForRouting(),
+ static_cast<HAL_AnalogTriggerType>(GetAnalogTriggerTypeForRouting()),
+ &status);
+ SetUpSourceEdge(true, false);
+ HAL_AttachInterruptHandler(m_interrupt, handler, param, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void InterruptableSensorBase::RequestInterrupts() {
+ if (StatusIsFatal()) return;
+
+ wpi_assert(m_interrupt == HAL_kInvalidHandle);
+ AllocateInterrupts(true);
+ if (StatusIsFatal()) return; // if allocate failed, out of interrupts
+
+ int32_t status = 0;
+ HAL_RequestInterrupts(
+ m_interrupt, GetPortHandleForRouting(),
+ static_cast<HAL_AnalogTriggerType>(GetAnalogTriggerTypeForRouting()),
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ SetUpSourceEdge(true, false);
+}
+
+void InterruptableSensorBase::CancelInterrupts() {
+ if (StatusIsFatal()) return;
+ wpi_assert(m_interrupt != HAL_kInvalidHandle);
+ int32_t status = 0;
+ HAL_CleanInterrupts(m_interrupt, &status);
+ // Ignore status, as an invalid handle just needs to be ignored.
+ m_interrupt = HAL_kInvalidHandle;
+}
+
+InterruptableSensorBase::WaitResult InterruptableSensorBase::WaitForInterrupt(
+ double timeout, bool ignorePrevious) {
+ if (StatusIsFatal()) return InterruptableSensorBase::kTimeout;
+ wpi_assert(m_interrupt != HAL_kInvalidHandle);
+ int32_t status = 0;
+ int result;
+
+ result = HAL_WaitForInterrupt(m_interrupt, timeout, ignorePrevious, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ // Rising edge result is the interrupt bit set in the byte 0xFF
+ // Falling edge result is the interrupt bit set in the byte 0xFF00
+ // Set any bit set to be true for that edge, and AND the 2 results
+ // together to match the existing enum for all interrupts
+ int32_t rising = (result & 0xFF) ? 0x1 : 0x0;
+ int32_t falling = ((result & 0xFF00) ? 0x0100 : 0x0);
+ return static_cast<WaitResult>(falling | rising);
+}
+
+void InterruptableSensorBase::EnableInterrupts() {
+ if (StatusIsFatal()) return;
+ wpi_assert(m_interrupt != HAL_kInvalidHandle);
+ int32_t status = 0;
+ HAL_EnableInterrupts(m_interrupt, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void InterruptableSensorBase::DisableInterrupts() {
+ if (StatusIsFatal()) return;
+ wpi_assert(m_interrupt != HAL_kInvalidHandle);
+ int32_t status = 0;
+ HAL_DisableInterrupts(m_interrupt, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+double InterruptableSensorBase::ReadRisingTimestamp() {
+ if (StatusIsFatal()) return 0.0;
+ wpi_assert(m_interrupt != HAL_kInvalidHandle);
+ int32_t status = 0;
+ int64_t timestamp = HAL_ReadInterruptRisingTimestamp(m_interrupt, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return timestamp * 1e-6;
+}
+
+double InterruptableSensorBase::ReadFallingTimestamp() {
+ if (StatusIsFatal()) return 0.0;
+ wpi_assert(m_interrupt != HAL_kInvalidHandle);
+ int32_t status = 0;
+ int64_t timestamp = HAL_ReadInterruptFallingTimestamp(m_interrupt, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return timestamp * 1e-6;
+}
+
+void InterruptableSensorBase::SetUpSourceEdge(bool risingEdge,
+ bool fallingEdge) {
+ if (StatusIsFatal()) return;
+ if (m_interrupt == HAL_kInvalidHandle) {
+ wpi_setWPIErrorWithContext(
+ NullParameter,
+ "You must call RequestInterrupts before SetUpSourceEdge");
+ return;
+ }
+ if (m_interrupt != HAL_kInvalidHandle) {
+ int32_t status = 0;
+ HAL_SetInterruptUpSourceEdge(m_interrupt, risingEdge, fallingEdge, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ }
+}
+
+void InterruptableSensorBase::AllocateInterrupts(bool watcher) {
+ wpi_assert(m_interrupt == HAL_kInvalidHandle);
+ // Expects the calling leaf class to allocate an interrupt index.
+ int32_t status = 0;
+ m_interrupt = HAL_InitializeInterrupts(watcher, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
diff --git a/wpilibc/src/main/native/cpp/IterativeRobot.cpp b/wpilibc/src/main/native/cpp/IterativeRobot.cpp
new file mode 100644
index 0000000..0f3add3
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/IterativeRobot.cpp
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/IterativeRobot.h"
+
+#include <hal/HAL.h>
+
+#include "frc/DriverStation.h"
+
+using namespace frc;
+
+static constexpr double kPacketPeriod = 0.02;
+
+IterativeRobot::IterativeRobot() : IterativeRobotBase(kPacketPeriod) {
+ HAL_Report(HALUsageReporting::kResourceType_Framework,
+ HALUsageReporting::kFramework_Iterative);
+}
+
+void IterativeRobot::StartCompetition() {
+ RobotInit();
+
+ // Tell the DS that the robot is ready to be enabled
+ HAL_ObserveUserProgramStarting();
+
+ // Loop forever, calling the appropriate mode-dependent function
+ while (true) {
+ // Wait for driver station data so the loop doesn't hog the CPU
+ DriverStation::GetInstance().WaitForData();
+
+ LoopFunc();
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp b/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp
new file mode 100644
index 0000000..771d81f
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp
@@ -0,0 +1,167 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/IterativeRobotBase.h"
+
+#include <cstdio>
+
+#include <hal/HAL.h>
+#include <wpi/SmallString.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/DriverStation.h"
+#include "frc/Timer.h"
+#include "frc/commands/Scheduler.h"
+#include "frc/livewindow/LiveWindow.h"
+#include "frc/smartdashboard/SmartDashboard.h"
+
+using namespace frc;
+
+IterativeRobotBase::IterativeRobotBase(double period)
+ : m_period(period),
+ m_watchdog(period, [this] { PrintLoopOverrunMessage(); }) {}
+
+void IterativeRobotBase::RobotInit() {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+}
+
+void IterativeRobotBase::DisabledInit() {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+}
+
+void IterativeRobotBase::AutonomousInit() {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+}
+
+void IterativeRobotBase::TeleopInit() {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+}
+
+void IterativeRobotBase::TestInit() {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+}
+
+void IterativeRobotBase::RobotPeriodic() {
+ static bool firstRun = true;
+ if (firstRun) {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+ firstRun = false;
+ }
+}
+
+void IterativeRobotBase::DisabledPeriodic() {
+ static bool firstRun = true;
+ if (firstRun) {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+ firstRun = false;
+ }
+}
+
+void IterativeRobotBase::AutonomousPeriodic() {
+ static bool firstRun = true;
+ if (firstRun) {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+ firstRun = false;
+ }
+}
+
+void IterativeRobotBase::TeleopPeriodic() {
+ static bool firstRun = true;
+ if (firstRun) {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+ firstRun = false;
+ }
+}
+
+void IterativeRobotBase::TestPeriodic() {
+ static bool firstRun = true;
+ if (firstRun) {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+ firstRun = false;
+ }
+}
+
+void IterativeRobotBase::LoopFunc() {
+ m_watchdog.Reset();
+
+ // Call the appropriate function depending upon the current robot mode
+ if (IsDisabled()) {
+ // Call DisabledInit() if we are now just entering disabled mode from
+ // either a different mode or from power-on.
+ if (m_lastMode != Mode::kDisabled) {
+ LiveWindow::GetInstance()->SetEnabled(false);
+ DisabledInit();
+ m_watchdog.AddEpoch("DisabledInit()");
+ m_lastMode = Mode::kDisabled;
+ }
+
+ HAL_ObserveUserProgramDisabled();
+ DisabledPeriodic();
+ m_watchdog.AddEpoch("DisabledPeriodic()");
+ } else if (IsAutonomous()) {
+ // Call AutonomousInit() if we are now just entering autonomous mode from
+ // either a different mode or from power-on.
+ if (m_lastMode != Mode::kAutonomous) {
+ LiveWindow::GetInstance()->SetEnabled(false);
+ AutonomousInit();
+ m_watchdog.AddEpoch("AutonomousInit()");
+ m_lastMode = Mode::kAutonomous;
+ }
+
+ HAL_ObserveUserProgramAutonomous();
+ AutonomousPeriodic();
+ m_watchdog.AddEpoch("AutonomousPeriodic()");
+ } else if (IsOperatorControl()) {
+ // Call TeleopInit() if we are now just entering teleop mode from
+ // either a different mode or from power-on.
+ if (m_lastMode != Mode::kTeleop) {
+ LiveWindow::GetInstance()->SetEnabled(false);
+ TeleopInit();
+ m_watchdog.AddEpoch("TeleopInit()");
+ m_lastMode = Mode::kTeleop;
+ Scheduler::GetInstance()->SetEnabled(true);
+ }
+
+ HAL_ObserveUserProgramTeleop();
+ TeleopPeriodic();
+ m_watchdog.AddEpoch("TeleopPeriodic()");
+ } else {
+ // Call TestInit() if we are now just entering test mode from
+ // either a different mode or from power-on.
+ if (m_lastMode != Mode::kTest) {
+ LiveWindow::GetInstance()->SetEnabled(true);
+ TestInit();
+ m_watchdog.AddEpoch("TestInit()");
+ m_lastMode = Mode::kTest;
+ }
+
+ HAL_ObserveUserProgramTest();
+ TestPeriodic();
+ m_watchdog.AddEpoch("TestPeriodic()");
+ }
+
+ RobotPeriodic();
+ m_watchdog.AddEpoch("RobotPeriodic()");
+ m_watchdog.Disable();
+ SmartDashboard::UpdateValues();
+
+ LiveWindow::GetInstance()->UpdateValues();
+
+ // Warn on loop time overruns
+ if (m_watchdog.IsExpired()) {
+ m_watchdog.PrintEpochs();
+ }
+}
+
+void IterativeRobotBase::PrintLoopOverrunMessage() {
+ wpi::SmallString<128> str;
+ wpi::raw_svector_ostream buf(str);
+
+ buf << "Loop time of " << m_period << "s overrun\n";
+
+ DriverStation::ReportWarning(str);
+}
diff --git a/wpilibc/src/main/native/cpp/Jaguar.cpp b/wpilibc/src/main/native/cpp/Jaguar.cpp
new file mode 100644
index 0000000..7bde6ba
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Jaguar.cpp
@@ -0,0 +1,30 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Jaguar.h"
+
+#include <hal/HAL.h>
+
+using namespace frc;
+
+Jaguar::Jaguar(int channel) : PWMSpeedController(channel) {
+ /* Input profile defined by Luminary Micro.
+ *
+ * Full reverse ranges from 0.671325ms to 0.6972211ms
+ * Proportional reverse ranges from 0.6972211ms to 1.4482078ms
+ * Neutral ranges from 1.4482078ms to 1.5517922ms
+ * Proportional forward ranges from 1.5517922ms to 2.3027789ms
+ * Full forward ranges from 2.3027789ms to 2.328675ms
+ */
+ SetBounds(2.31, 1.55, 1.507, 1.454, .697);
+ SetPeriodMultiplier(kPeriodMultiplier_1X);
+ SetSpeed(0.0);
+ SetZeroLatch();
+
+ HAL_Report(HALUsageReporting::kResourceType_Jaguar, GetChannel());
+ SetName("Jaguar", GetChannel());
+}
diff --git a/wpilibc/src/main/native/cpp/Joystick.cpp b/wpilibc/src/main/native/cpp/Joystick.cpp
new file mode 100644
index 0000000..da77d94
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Joystick.cpp
@@ -0,0 +1,133 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Joystick.h"
+
+#include <cmath>
+
+#include <hal/HAL.h>
+
+#include "frc/DriverStation.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+constexpr double kPi = 3.14159265358979323846;
+
+Joystick::Joystick(int port) : GenericHID(port) {
+ m_axes[Axis::kX] = kDefaultXChannel;
+ m_axes[Axis::kY] = kDefaultYChannel;
+ m_axes[Axis::kZ] = kDefaultZChannel;
+ m_axes[Axis::kTwist] = kDefaultTwistChannel;
+ m_axes[Axis::kThrottle] = kDefaultThrottleChannel;
+
+ HAL_Report(HALUsageReporting::kResourceType_Joystick, port);
+}
+
+void Joystick::SetXChannel(int channel) { m_axes[Axis::kX] = channel; }
+
+void Joystick::SetYChannel(int channel) { m_axes[Axis::kY] = channel; }
+
+void Joystick::SetZChannel(int channel) { m_axes[Axis::kZ] = channel; }
+
+void Joystick::SetTwistChannel(int channel) { m_axes[Axis::kTwist] = channel; }
+
+void Joystick::SetThrottleChannel(int channel) {
+ m_axes[Axis::kThrottle] = channel;
+}
+
+void Joystick::SetAxisChannel(AxisType axis, int channel) {
+ m_axes[axis] = channel;
+}
+
+int Joystick::GetXChannel() const { return m_axes[Axis::kX]; }
+
+int Joystick::GetYChannel() const { return m_axes[Axis::kY]; }
+
+int Joystick::GetZChannel() const { return m_axes[Axis::kZ]; }
+
+int Joystick::GetTwistChannel() const { return m_axes[Axis::kTwist]; }
+
+int Joystick::GetThrottleChannel() const { return m_axes[Axis::kThrottle]; }
+
+double Joystick::GetX(JoystickHand hand) const {
+ return GetRawAxis(m_axes[Axis::kX]);
+}
+
+double Joystick::GetY(JoystickHand hand) const {
+ return GetRawAxis(m_axes[Axis::kY]);
+}
+
+double Joystick::GetZ() const { return GetRawAxis(m_axes[Axis::kZ]); }
+
+double Joystick::GetTwist() const { return GetRawAxis(m_axes[Axis::kTwist]); }
+
+double Joystick::GetThrottle() const {
+ return GetRawAxis(m_axes[Axis::kThrottle]);
+}
+
+double Joystick::GetAxis(AxisType axis) const {
+ switch (axis) {
+ case kXAxis:
+ return GetX();
+ case kYAxis:
+ return GetY();
+ case kZAxis:
+ return GetZ();
+ case kTwistAxis:
+ return GetTwist();
+ case kThrottleAxis:
+ return GetThrottle();
+ default:
+ wpi_setWPIError(BadJoystickAxis);
+ return 0.0;
+ }
+}
+
+bool Joystick::GetTrigger() const { return GetRawButton(Button::kTrigger); }
+
+bool Joystick::GetTriggerPressed() {
+ return GetRawButtonPressed(Button::kTrigger);
+}
+
+bool Joystick::GetTriggerReleased() {
+ return GetRawButtonReleased(Button::kTrigger);
+}
+
+bool Joystick::GetTop() const { return GetRawButton(Button::kTop); }
+
+bool Joystick::GetTopPressed() { return GetRawButtonPressed(Button::kTop); }
+
+bool Joystick::GetTopReleased() { return GetRawButtonReleased(Button::kTop); }
+
+Joystick* Joystick::GetStickForPort(int port) {
+ static std::array<std::unique_ptr<Joystick>, DriverStation::kJoystickPorts>
+ joysticks{};
+ auto stick = joysticks[port].get();
+ if (stick == nullptr) {
+ joysticks[port] = std::make_unique<Joystick>(port);
+ stick = joysticks[port].get();
+ }
+ return stick;
+}
+
+bool Joystick::GetButton(ButtonType button) const {
+ int temp = button;
+ return GetRawButton(static_cast<Button>(temp));
+}
+
+double Joystick::GetMagnitude() const {
+ return std::sqrt(std::pow(GetX(), 2) + std::pow(GetY(), 2));
+}
+
+double Joystick::GetDirectionRadians() const {
+ return std::atan2(GetX(), -GetY());
+}
+
+double Joystick::GetDirectionDegrees() const {
+ return (180 / kPi) * GetDirectionRadians();
+}
diff --git a/wpilibc/src/main/native/cpp/JoystickBase.cpp b/wpilibc/src/main/native/cpp/JoystickBase.cpp
new file mode 100644
index 0000000..8e6858c
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/JoystickBase.cpp
@@ -0,0 +1,12 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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 "frc/JoystickBase.h"
+
+using namespace frc;
+
+JoystickBase::JoystickBase(int port) : GenericHID(port) {}
diff --git a/wpilibc/src/main/native/cpp/MotorSafety.cpp b/wpilibc/src/main/native/cpp/MotorSafety.cpp
new file mode 100644
index 0000000..aff85d8
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/MotorSafety.cpp
@@ -0,0 +1,111 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/MotorSafety.h"
+
+#include <algorithm>
+#include <utility>
+
+#include <wpi/SmallPtrSet.h>
+#include <wpi/SmallString.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/DriverStation.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+static wpi::SmallPtrSet<MotorSafety*, 32> instanceList;
+static wpi::mutex listMutex;
+
+MotorSafety::MotorSafety() {
+ std::lock_guard<wpi::mutex> lock(listMutex);
+ instanceList.insert(this);
+}
+
+MotorSafety::~MotorSafety() {
+ std::lock_guard<wpi::mutex> lock(listMutex);
+ instanceList.erase(this);
+}
+
+MotorSafety::MotorSafety(MotorSafety&& rhs)
+ : ErrorBase(std::move(rhs)),
+ m_expiration(std::move(rhs.m_expiration)),
+ m_enabled(std::move(rhs.m_enabled)),
+ m_stopTime(std::move(rhs.m_stopTime)) {}
+
+MotorSafety& MotorSafety::operator=(MotorSafety&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+
+ m_expiration = std::move(rhs.m_expiration);
+ m_enabled = std::move(rhs.m_enabled);
+ m_stopTime = std::move(rhs.m_stopTime);
+
+ return *this;
+}
+
+void MotorSafety::Feed() {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_stopTime = Timer::GetFPGATimestamp() + m_expiration;
+}
+
+void MotorSafety::SetExpiration(double expirationTime) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_expiration = expirationTime;
+}
+
+double MotorSafety::GetExpiration() const {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ return m_expiration;
+}
+
+bool MotorSafety::IsAlive() const {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ return !m_enabled || m_stopTime > Timer::GetFPGATimestamp();
+}
+
+void MotorSafety::SetSafetyEnabled(bool enabled) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_enabled = enabled;
+}
+
+bool MotorSafety::IsSafetyEnabled() const {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ return m_enabled;
+}
+
+void MotorSafety::Check() {
+ bool enabled;
+ double stopTime;
+
+ {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ enabled = m_enabled;
+ stopTime = m_stopTime;
+ }
+
+ DriverStation& ds = DriverStation::GetInstance();
+ if (!enabled || ds.IsDisabled() || ds.IsTest()) {
+ return;
+ }
+
+ if (stopTime < Timer::GetFPGATimestamp()) {
+ wpi::SmallString<128> buf;
+ wpi::raw_svector_ostream desc(buf);
+ GetDescription(desc);
+ desc << "... Output not updated often enough.";
+ wpi_setWPIErrorWithContext(Timeout, desc.str());
+ StopMotor();
+ }
+}
+
+void MotorSafety::CheckMotors() {
+ std::lock_guard<wpi::mutex> lock(listMutex);
+ for (auto elem : instanceList) {
+ elem->Check();
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/NidecBrushless.cpp b/wpilibc/src/main/native/cpp/NidecBrushless.cpp
new file mode 100644
index 0000000..0ccc7c7
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/NidecBrushless.cpp
@@ -0,0 +1,73 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/NidecBrushless.h"
+
+#include <hal/HAL.h>
+
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+NidecBrushless::NidecBrushless(int pwmChannel, int dioChannel)
+ : m_dio(dioChannel), m_pwm(pwmChannel) {
+ AddChild(&m_dio);
+ AddChild(&m_pwm);
+ SetExpiration(0.0);
+ SetSafetyEnabled(false);
+
+ // the dio controls the output (in PWM mode)
+ m_dio.SetPWMRate(15625);
+ m_dio.EnablePWM(0.5);
+
+ HAL_Report(HALUsageReporting::kResourceType_NidecBrushless, pwmChannel);
+ SetName("Nidec Brushless", pwmChannel);
+}
+
+void NidecBrushless::Set(double speed) {
+ if (!m_disabled) {
+ m_speed = speed;
+ m_dio.UpdateDutyCycle(0.5 + 0.5 * (m_isInverted ? -speed : speed));
+ m_pwm.SetRaw(0xffff);
+ }
+ Feed();
+}
+
+double NidecBrushless::Get() const { return m_speed; }
+
+void NidecBrushless::SetInverted(bool isInverted) { m_isInverted = isInverted; }
+
+bool NidecBrushless::GetInverted() const { return m_isInverted; }
+
+void NidecBrushless::Disable() {
+ m_disabled = true;
+ m_dio.UpdateDutyCycle(0.5);
+ m_pwm.SetDisabled();
+}
+
+void NidecBrushless::Enable() { m_disabled = false; }
+
+void NidecBrushless::PIDWrite(double output) { Set(output); }
+
+void NidecBrushless::StopMotor() {
+ m_dio.UpdateDutyCycle(0.5);
+ m_pwm.SetDisabled();
+}
+
+void NidecBrushless::GetDescription(wpi::raw_ostream& desc) const {
+ desc << "Nidec " << GetChannel();
+}
+
+int NidecBrushless::GetChannel() const { return m_pwm.GetChannel(); }
+
+void NidecBrushless::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Nidec Brushless");
+ builder.SetActuator(true);
+ builder.SetSafeState([=]() { StopMotor(); });
+ builder.AddDoubleProperty("Value", [=]() { return Get(); },
+ [=](double value) { Set(value); });
+}
diff --git a/wpilibc/src/main/native/cpp/Notifier.cpp b/wpilibc/src/main/native/cpp/Notifier.cpp
new file mode 100644
index 0000000..69a9f4e
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Notifier.cpp
@@ -0,0 +1,131 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Notifier.h"
+
+#include <utility>
+
+#include <hal/HAL.h>
+
+#include "frc/Timer.h"
+#include "frc/Utility.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+Notifier::Notifier(TimerEventHandler handler) {
+ if (handler == nullptr)
+ wpi_setWPIErrorWithContext(NullParameter, "handler must not be nullptr");
+ m_handler = handler;
+ int32_t status = 0;
+ m_notifier = HAL_InitializeNotifier(&status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ m_thread = std::thread([=] {
+ for (;;) {
+ int32_t status = 0;
+ HAL_NotifierHandle notifier = m_notifier.load();
+ if (notifier == 0) break;
+ uint64_t curTime = HAL_WaitForNotifierAlarm(notifier, &status);
+ if (curTime == 0 || status != 0) break;
+
+ TimerEventHandler handler;
+ {
+ std::lock_guard<wpi::mutex> lock(m_processMutex);
+ handler = m_handler;
+ if (m_periodic) {
+ m_expirationTime += m_period;
+ UpdateAlarm();
+ } else {
+ // need to update the alarm to cause it to wait again
+ UpdateAlarm(UINT64_MAX);
+ }
+ }
+
+ // call callback
+ if (handler) handler();
+ }
+ });
+}
+
+Notifier::~Notifier() {
+ int32_t status = 0;
+ // atomically set handle to 0, then clean
+ HAL_NotifierHandle handle = m_notifier.exchange(0);
+ HAL_StopNotifier(handle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ // Join the thread to ensure the handler has exited.
+ if (m_thread.joinable()) m_thread.join();
+
+ HAL_CleanNotifier(handle, &status);
+}
+
+Notifier::Notifier(Notifier&& rhs)
+ : ErrorBase(std::move(rhs)),
+ m_thread(std::move(rhs.m_thread)),
+ m_notifier(rhs.m_notifier.load()),
+ m_handler(std::move(rhs.m_handler)),
+ m_expirationTime(std::move(rhs.m_expirationTime)),
+ m_period(std::move(rhs.m_period)),
+ m_periodic(std::move(rhs.m_periodic)) {
+ rhs.m_notifier = HAL_kInvalidHandle;
+}
+
+Notifier& Notifier::operator=(Notifier&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+
+ m_thread = std::move(rhs.m_thread);
+ m_notifier = rhs.m_notifier.load();
+ rhs.m_notifier = HAL_kInvalidHandle;
+ m_handler = std::move(rhs.m_handler);
+ m_expirationTime = std::move(rhs.m_expirationTime);
+ m_period = std::move(rhs.m_period);
+ m_periodic = std::move(rhs.m_periodic);
+
+ return *this;
+}
+
+void Notifier::SetHandler(TimerEventHandler handler) {
+ std::lock_guard<wpi::mutex> lock(m_processMutex);
+ m_handler = handler;
+}
+
+void Notifier::StartSingle(double delay) {
+ std::lock_guard<wpi::mutex> lock(m_processMutex);
+ m_periodic = false;
+ m_period = delay;
+ m_expirationTime = Timer::GetFPGATimestamp() + m_period;
+ UpdateAlarm();
+}
+
+void Notifier::StartPeriodic(double period) {
+ std::lock_guard<wpi::mutex> lock(m_processMutex);
+ m_periodic = true;
+ m_period = period;
+ m_expirationTime = Timer::GetFPGATimestamp() + m_period;
+ UpdateAlarm();
+}
+
+void Notifier::Stop() {
+ int32_t status = 0;
+ HAL_CancelNotifierAlarm(m_notifier, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Notifier::UpdateAlarm(uint64_t triggerTime) {
+ int32_t status = 0;
+ // Return if we are being destructed, or were not created successfully
+ auto notifier = m_notifier.load();
+ if (notifier == 0) return;
+ HAL_UpdateNotifierAlarm(notifier, triggerTime, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Notifier::UpdateAlarm() {
+ UpdateAlarm(static_cast<uint64_t>(m_expirationTime * 1e6));
+}
diff --git a/wpilibc/src/main/native/cpp/PIDBase.cpp b/wpilibc/src/main/native/cpp/PIDBase.cpp
new file mode 100644
index 0000000..872a45a
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/PIDBase.cpp
@@ -0,0 +1,360 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/PIDBase.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include <hal/HAL.h>
+
+#include "frc/PIDOutput.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+template <class T>
+constexpr const T& clamp(const T& value, const T& low, const T& high) {
+ return std::max(low, std::min(value, high));
+}
+
+PIDBase::PIDBase(double Kp, double Ki, double Kd, PIDSource& source,
+ PIDOutput& output)
+ : PIDBase(Kp, Ki, Kd, 0.0, source, output) {}
+
+PIDBase::PIDBase(double Kp, double Ki, double Kd, double Kf, PIDSource& source,
+ PIDOutput& output)
+ : SendableBase(false) {
+ m_P = Kp;
+ m_I = Ki;
+ m_D = Kd;
+ m_F = Kf;
+
+ // Save original source
+ m_origSource = std::shared_ptr<PIDSource>(&source, NullDeleter<PIDSource>());
+
+ // Create LinearDigitalFilter with original source as its source argument
+ m_filter = LinearDigitalFilter::MovingAverage(m_origSource, 1);
+ m_pidInput = &m_filter;
+
+ m_pidOutput = &output;
+
+ m_setpointTimer.Start();
+
+ static int instances = 0;
+ instances++;
+ HAL_Report(HALUsageReporting::kResourceType_PIDController, instances);
+ SetName("PIDController", instances);
+}
+
+double PIDBase::Get() const {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ return m_result;
+}
+
+void PIDBase::SetContinuous(bool continuous) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_continuous = continuous;
+}
+
+void PIDBase::SetInputRange(double minimumInput, double maximumInput) {
+ {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_minimumInput = minimumInput;
+ m_maximumInput = maximumInput;
+ m_inputRange = maximumInput - minimumInput;
+ }
+
+ SetSetpoint(m_setpoint);
+}
+
+void PIDBase::SetOutputRange(double minimumOutput, double maximumOutput) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_minimumOutput = minimumOutput;
+ m_maximumOutput = maximumOutput;
+}
+
+void PIDBase::SetPID(double p, double i, double d) {
+ {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_P = p;
+ m_I = i;
+ m_D = d;
+ }
+}
+
+void PIDBase::SetPID(double p, double i, double d, double f) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_P = p;
+ m_I = i;
+ m_D = d;
+ m_F = f;
+}
+
+void PIDBase::SetP(double p) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_P = p;
+}
+
+void PIDBase::SetI(double i) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_I = i;
+}
+
+void PIDBase::SetD(double d) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_D = d;
+}
+
+void PIDBase::SetF(double f) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_F = f;
+}
+
+double PIDBase::GetP() const {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ return m_P;
+}
+
+double PIDBase::GetI() const {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ return m_I;
+}
+
+double PIDBase::GetD() const {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ return m_D;
+}
+
+double PIDBase::GetF() const {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ return m_F;
+}
+
+void PIDBase::SetSetpoint(double setpoint) {
+ {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+
+ if (m_maximumInput > m_minimumInput) {
+ if (setpoint > m_maximumInput)
+ m_setpoint = m_maximumInput;
+ else if (setpoint < m_minimumInput)
+ m_setpoint = m_minimumInput;
+ else
+ m_setpoint = setpoint;
+ } else {
+ m_setpoint = setpoint;
+ }
+ }
+}
+
+double PIDBase::GetSetpoint() const {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ return m_setpoint;
+}
+
+double PIDBase::GetDeltaSetpoint() const {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ return (m_setpoint - m_prevSetpoint) / m_setpointTimer.Get();
+}
+
+double PIDBase::GetError() const {
+ double setpoint = GetSetpoint();
+ {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ return GetContinuousError(setpoint - m_pidInput->PIDGet());
+ }
+}
+
+double PIDBase::GetAvgError() const { return GetError(); }
+
+void PIDBase::SetPIDSourceType(PIDSourceType pidSource) {
+ m_pidInput->SetPIDSourceType(pidSource);
+}
+
+PIDSourceType PIDBase::GetPIDSourceType() const {
+ return m_pidInput->GetPIDSourceType();
+}
+
+void PIDBase::SetTolerance(double percent) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_toleranceType = kPercentTolerance;
+ m_tolerance = percent;
+}
+
+void PIDBase::SetAbsoluteTolerance(double absTolerance) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_toleranceType = kAbsoluteTolerance;
+ m_tolerance = absTolerance;
+}
+
+void PIDBase::SetPercentTolerance(double percent) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_toleranceType = kPercentTolerance;
+ m_tolerance = percent;
+}
+
+void PIDBase::SetToleranceBuffer(int bufLength) {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+
+ // Create LinearDigitalFilter with original source as its source argument
+ m_filter = LinearDigitalFilter::MovingAverage(m_origSource, bufLength);
+ m_pidInput = &m_filter;
+}
+
+bool PIDBase::OnTarget() const {
+ double error = GetError();
+
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ switch (m_toleranceType) {
+ case kPercentTolerance:
+ return std::fabs(error) < m_tolerance / 100 * m_inputRange;
+ break;
+ case kAbsoluteTolerance:
+ return std::fabs(error) < m_tolerance;
+ break;
+ case kNoTolerance:
+ // TODO: this case needs an error
+ return false;
+ }
+ return false;
+}
+
+void PIDBase::Reset() {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_prevError = 0;
+ m_totalError = 0;
+ m_result = 0;
+}
+
+void PIDBase::PIDWrite(double output) { SetSetpoint(output); }
+
+void PIDBase::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("PIDController");
+ builder.SetSafeState([=]() { Reset(); });
+ builder.AddDoubleProperty("p", [=]() { return GetP(); },
+ [=](double value) { SetP(value); });
+ builder.AddDoubleProperty("i", [=]() { return GetI(); },
+ [=](double value) { SetI(value); });
+ builder.AddDoubleProperty("d", [=]() { return GetD(); },
+ [=](double value) { SetD(value); });
+ builder.AddDoubleProperty("f", [=]() { return GetF(); },
+ [=](double value) { SetF(value); });
+ builder.AddDoubleProperty("setpoint", [=]() { return GetSetpoint(); },
+ [=](double value) { SetSetpoint(value); });
+}
+
+void PIDBase::Calculate() {
+ if (m_origSource == nullptr || m_pidOutput == nullptr) return;
+
+ bool enabled;
+ {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ enabled = m_enabled;
+ }
+
+ if (enabled) {
+ double input;
+
+ // Storage for function inputs
+ PIDSourceType pidSourceType;
+ double P;
+ double I;
+ double D;
+ double feedForward = CalculateFeedForward();
+ double minimumOutput;
+ double maximumOutput;
+
+ // Storage for function input-outputs
+ double prevError;
+ double error;
+ double totalError;
+
+ {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+
+ input = m_pidInput->PIDGet();
+
+ pidSourceType = m_pidInput->GetPIDSourceType();
+ P = m_P;
+ I = m_I;
+ D = m_D;
+ minimumOutput = m_minimumOutput;
+ maximumOutput = m_maximumOutput;
+
+ prevError = m_prevError;
+ error = GetContinuousError(m_setpoint - input);
+ totalError = m_totalError;
+ }
+
+ // Storage for function outputs
+ double result;
+
+ if (pidSourceType == PIDSourceType::kRate) {
+ if (P != 0) {
+ totalError =
+ clamp(totalError + error, minimumOutput / P, maximumOutput / P);
+ }
+
+ result = D * error + P * totalError + feedForward;
+ } else {
+ if (I != 0) {
+ totalError =
+ clamp(totalError + error, minimumOutput / I, maximumOutput / I);
+ }
+
+ result =
+ P * error + I * totalError + D * (error - prevError) + feedForward;
+ }
+
+ result = clamp(result, minimumOutput, maximumOutput);
+
+ {
+ // Ensures m_enabled check and PIDWrite() call occur atomically
+ std::lock_guard<wpi::mutex> pidWriteLock(m_pidWriteMutex);
+ std::unique_lock<wpi::mutex> mainLock(m_thisMutex);
+ if (m_enabled) {
+ // Don't block other PIDBase operations on PIDWrite()
+ mainLock.unlock();
+
+ m_pidOutput->PIDWrite(result);
+ }
+ }
+
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_prevError = m_error;
+ m_error = error;
+ m_totalError = totalError;
+ m_result = result;
+ }
+}
+
+double PIDBase::CalculateFeedForward() {
+ if (m_pidInput->GetPIDSourceType() == PIDSourceType::kRate) {
+ return m_F * GetSetpoint();
+ } else {
+ double temp = m_F * GetDeltaSetpoint();
+ m_prevSetpoint = m_setpoint;
+ m_setpointTimer.Reset();
+ return temp;
+ }
+}
+
+double PIDBase::GetContinuousError(double error) const {
+ if (m_continuous && m_inputRange != 0) {
+ error = std::fmod(error, m_inputRange);
+ if (std::fabs(error) > m_inputRange / 2) {
+ if (error > 0) {
+ return error - m_inputRange;
+ } else {
+ return error + m_inputRange;
+ }
+ }
+ }
+
+ return error;
+}
diff --git a/wpilibc/src/main/native/cpp/PIDController.cpp b/wpilibc/src/main/native/cpp/PIDController.cpp
new file mode 100644
index 0000000..b1c51c6
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/PIDController.cpp
@@ -0,0 +1,85 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/PIDController.h"
+
+#include "frc/Notifier.h"
+#include "frc/PIDOutput.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+PIDController::PIDController(double Kp, double Ki, double Kd, PIDSource* source,
+ PIDOutput* output, double period)
+ : PIDController(Kp, Ki, Kd, 0.0, *source, *output, period) {}
+
+PIDController::PIDController(double Kp, double Ki, double Kd, double Kf,
+ PIDSource* source, PIDOutput* output,
+ double period)
+ : PIDController(Kp, Ki, Kd, Kf, *source, *output, period) {}
+
+PIDController::PIDController(double Kp, double Ki, double Kd, PIDSource& source,
+ PIDOutput& output, double period)
+ : PIDController(Kp, Ki, Kd, 0.0, source, output, period) {}
+
+PIDController::PIDController(double Kp, double Ki, double Kd, double Kf,
+ PIDSource& source, PIDOutput& output,
+ double period)
+ : PIDBase(Kp, Ki, Kd, Kf, source, output) {
+ m_controlLoop = std::make_unique<Notifier>(&PIDController::Calculate, this);
+ m_controlLoop->StartPeriodic(period);
+}
+
+PIDController::~PIDController() {
+ // Forcefully stopping the notifier so the callback can successfully run.
+ m_controlLoop->Stop();
+}
+
+void PIDController::Enable() {
+ {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ m_enabled = true;
+ }
+}
+
+void PIDController::Disable() {
+ {
+ // Ensures m_enabled modification and PIDWrite() call occur atomically
+ std::lock_guard<wpi::mutex> pidWriteLock(m_pidWriteMutex);
+ {
+ std::lock_guard<wpi::mutex> mainLock(m_thisMutex);
+ m_enabled = false;
+ }
+
+ m_pidOutput->PIDWrite(0);
+ }
+}
+
+void PIDController::SetEnabled(bool enable) {
+ if (enable) {
+ Enable();
+ } else {
+ Disable();
+ }
+}
+
+bool PIDController::IsEnabled() const {
+ std::lock_guard<wpi::mutex> lock(m_thisMutex);
+ return m_enabled;
+}
+
+void PIDController::Reset() {
+ Disable();
+
+ PIDBase::Reset();
+}
+
+void PIDController::InitSendable(SendableBuilder& builder) {
+ PIDBase::InitSendable(builder);
+ builder.AddBooleanProperty("enabled", [=]() { return IsEnabled(); },
+ [=](bool value) { SetEnabled(value); });
+}
diff --git a/wpilibc/src/main/native/cpp/PIDSource.cpp b/wpilibc/src/main/native/cpp/PIDSource.cpp
new file mode 100644
index 0000000..28291dd
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/PIDSource.cpp
@@ -0,0 +1,16 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/PIDSource.h"
+
+using namespace frc;
+
+void PIDSource::SetPIDSourceType(PIDSourceType pidSource) {
+ m_pidSource = pidSource;
+}
+
+PIDSourceType PIDSource::GetPIDSourceType() const { return m_pidSource; }
diff --git a/wpilibc/src/main/native/cpp/PWM.cpp b/wpilibc/src/main/native/cpp/PWM.cpp
new file mode 100644
index 0000000..603c94b
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/PWM.cpp
@@ -0,0 +1,220 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/PWM.h"
+
+#include <utility>
+
+#include <hal/HAL.h>
+#include <hal/PWM.h>
+#include <hal/Ports.h>
+
+#include "frc/SensorUtil.h"
+#include "frc/Utility.h"
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+PWM::PWM(int channel) {
+ if (!SensorUtil::CheckPWMChannel(channel)) {
+ wpi_setWPIErrorWithContext(ChannelIndexOutOfRange,
+ "PWM Channel " + wpi::Twine(channel));
+ return;
+ }
+
+ int32_t status = 0;
+ m_handle = HAL_InitializePWMPort(HAL_GetPort(channel), &status);
+ if (status != 0) {
+ wpi_setErrorWithContextRange(status, 0, HAL_GetNumPWMChannels(), channel,
+ HAL_GetErrorMessage(status));
+ m_channel = std::numeric_limits<int>::max();
+ m_handle = HAL_kInvalidHandle;
+ return;
+ }
+
+ m_channel = channel;
+
+ HAL_SetPWMDisabled(m_handle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ status = 0;
+ HAL_SetPWMEliminateDeadband(m_handle, false, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ HAL_Report(HALUsageReporting::kResourceType_PWM, channel);
+ SetName("PWM", channel);
+
+ SetSafetyEnabled(false);
+}
+
+PWM::~PWM() {
+ int32_t status = 0;
+
+ HAL_SetPWMDisabled(m_handle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ HAL_FreePWMPort(m_handle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+PWM::PWM(PWM&& rhs)
+ : MotorSafety(std::move(rhs)),
+ SendableBase(std::move(rhs)),
+ m_channel(std::move(rhs.m_channel)) {
+ std::swap(m_handle, rhs.m_handle);
+}
+
+PWM& PWM::operator=(PWM&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+ SendableBase::operator=(std::move(rhs));
+
+ m_channel = std::move(rhs.m_channel);
+ std::swap(m_handle, rhs.m_handle);
+
+ return *this;
+}
+
+void PWM::StopMotor() { SetDisabled(); }
+
+void PWM::GetDescription(wpi::raw_ostream& desc) const {
+ desc << "PWM " << GetChannel();
+}
+
+void PWM::SetRaw(uint16_t value) {
+ if (StatusIsFatal()) return;
+
+ int32_t status = 0;
+ HAL_SetPWMRaw(m_handle, value, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+uint16_t PWM::GetRaw() const {
+ if (StatusIsFatal()) return 0;
+
+ int32_t status = 0;
+ uint16_t value = HAL_GetPWMRaw(m_handle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ return value;
+}
+
+void PWM::SetPosition(double pos) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetPWMPosition(m_handle, pos, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+double PWM::GetPosition() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double position = HAL_GetPWMPosition(m_handle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return position;
+}
+
+void PWM::SetSpeed(double speed) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetPWMSpeed(m_handle, speed, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ Feed();
+}
+
+double PWM::GetSpeed() const {
+ if (StatusIsFatal()) return 0.0;
+ int32_t status = 0;
+ double speed = HAL_GetPWMSpeed(m_handle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return speed;
+}
+
+void PWM::SetDisabled() {
+ if (StatusIsFatal()) return;
+
+ int32_t status = 0;
+
+ HAL_SetPWMDisabled(m_handle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void PWM::SetPeriodMultiplier(PeriodMultiplier mult) {
+ if (StatusIsFatal()) return;
+
+ int32_t status = 0;
+
+ switch (mult) {
+ case kPeriodMultiplier_4X:
+ HAL_SetPWMPeriodScale(m_handle, 3,
+ &status); // Squelch 3 out of 4 outputs
+ break;
+ case kPeriodMultiplier_2X:
+ HAL_SetPWMPeriodScale(m_handle, 1,
+ &status); // Squelch 1 out of 2 outputs
+ break;
+ case kPeriodMultiplier_1X:
+ HAL_SetPWMPeriodScale(m_handle, 0, &status); // Don't squelch any outputs
+ break;
+ default:
+ wpi_assert(false);
+ }
+
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void PWM::SetZeroLatch() {
+ if (StatusIsFatal()) return;
+
+ int32_t status = 0;
+
+ HAL_LatchPWMZero(m_handle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void PWM::EnableDeadbandElimination(bool eliminateDeadband) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetPWMEliminateDeadband(m_handle, eliminateDeadband, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void PWM::SetBounds(double max, double deadbandMax, double center,
+ double deadbandMin, double min) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetPWMConfig(m_handle, max, deadbandMax, center, deadbandMin, min,
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void PWM::SetRawBounds(int max, int deadbandMax, int center, int deadbandMin,
+ int min) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetPWMConfigRaw(m_handle, max, deadbandMax, center, deadbandMin, min,
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void PWM::GetRawBounds(int* max, int* deadbandMax, int* center,
+ int* deadbandMin, int* min) {
+ int32_t status = 0;
+ HAL_GetPWMConfigRaw(m_handle, max, deadbandMax, center, deadbandMin, min,
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int PWM::GetChannel() const { return m_channel; }
+
+void PWM::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("PWM");
+ builder.SetActuator(true);
+ builder.SetSafeState([=]() { SetDisabled(); });
+ builder.AddDoubleProperty("Value", [=]() { return GetRaw(); },
+ [=](double value) { SetRaw(value); });
+}
diff --git a/wpilibc/src/main/native/cpp/PWMSpeedController.cpp b/wpilibc/src/main/native/cpp/PWMSpeedController.cpp
new file mode 100644
index 0000000..ea298de
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/PWMSpeedController.cpp
@@ -0,0 +1,40 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/PWMSpeedController.h"
+
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+void PWMSpeedController::Set(double speed) {
+ SetSpeed(m_isInverted ? -speed : speed);
+}
+
+double PWMSpeedController::Get() const { return GetSpeed(); }
+
+void PWMSpeedController::SetInverted(bool isInverted) {
+ m_isInverted = isInverted;
+}
+
+bool PWMSpeedController::GetInverted() const { return m_isInverted; }
+
+void PWMSpeedController::Disable() { SetDisabled(); }
+
+void PWMSpeedController::StopMotor() { PWM::StopMotor(); }
+
+void PWMSpeedController::PIDWrite(double output) { Set(output); }
+
+PWMSpeedController::PWMSpeedController(int channel) : PWM(channel) {}
+
+void PWMSpeedController::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Speed Controller");
+ builder.SetActuator(true);
+ builder.SetSafeState([=]() { SetDisabled(); });
+ builder.AddDoubleProperty("Value", [=]() { return GetSpeed(); },
+ [=](double value) { SetSpeed(value); });
+}
diff --git a/wpilibc/src/main/native/cpp/PWMTalonSRX.cpp b/wpilibc/src/main/native/cpp/PWMTalonSRX.cpp
new file mode 100644
index 0000000..ccb50b6
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/PWMTalonSRX.cpp
@@ -0,0 +1,34 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/PWMTalonSRX.h"
+
+#include <hal/HAL.h>
+
+using namespace frc;
+
+PWMTalonSRX::PWMTalonSRX(int channel) : PWMSpeedController(channel) {
+ /* Note that the PWMTalonSRX uses the following bounds for PWM values. These
+ * values should work reasonably well for most controllers, but if users
+ * experience issues such as asymmetric behavior around the deadband or
+ * inability to saturate the controller in either direction, calibration is
+ * recommended. The calibration procedure can be found in the TalonSRX User
+ * Manual available from Cross The Road Electronics.
+ * 2.004ms = full "forward"
+ * 1.52ms = the "high end" of the deadband range
+ * 1.50ms = center of the deadband range (off)
+ * 1.48ms = the "low end" of the deadband range
+ * 0.997ms = full "reverse"
+ */
+ SetBounds(2.004, 1.52, 1.50, 1.48, .997);
+ SetPeriodMultiplier(kPeriodMultiplier_1X);
+ SetSpeed(0.0);
+ SetZeroLatch();
+
+ HAL_Report(HALUsageReporting::kResourceType_PWMTalonSRX, GetChannel());
+ SetName("PWMTalonSRX", GetChannel());
+}
diff --git a/wpilibc/src/main/native/cpp/PWMVictorSPX.cpp b/wpilibc/src/main/native/cpp/PWMVictorSPX.cpp
new file mode 100644
index 0000000..b4f1fd2
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/PWMVictorSPX.cpp
@@ -0,0 +1,34 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/PWMVictorSPX.h"
+
+#include <hal/HAL.h>
+
+using namespace frc;
+
+PWMVictorSPX::PWMVictorSPX(int channel) : PWMSpeedController(channel) {
+ /* Note that the PWMVictorSPX uses the following bounds for PWM values. These
+ * values should work reasonably well for most controllers, but if users
+ * experience issues such as asymmetric behavior around the deadband or
+ * inability to saturate the controller in either direction, calibration is
+ * recommended. The calibration procedure can be found in the VictorSPX User
+ * Manual available from Cross The Road Electronics.
+ * 2.004ms = full "forward"
+ * 1.52ms = the "high end" of the deadband range
+ * 1.50ms = center of the deadband range (off)
+ * 1.48ms = the "low end" of the deadband range
+ * 0.997ms = full "reverse"
+ */
+ SetBounds(2.004, 1.52, 1.50, 1.48, .997);
+ SetPeriodMultiplier(kPeriodMultiplier_1X);
+ SetSpeed(0.0);
+ SetZeroLatch();
+
+ HAL_Report(HALUsageReporting::kResourceType_PWMVictorSPX, GetChannel());
+ SetName("PWMVictorSPX", GetChannel());
+}
diff --git a/wpilibc/src/main/native/cpp/PowerDistributionPanel.cpp b/wpilibc/src/main/native/cpp/PowerDistributionPanel.cpp
new file mode 100644
index 0000000..8872028
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/PowerDistributionPanel.cpp
@@ -0,0 +1,148 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. 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 "frc/PowerDistributionPanel.h"
+
+#include <hal/HAL.h>
+#include <hal/PDP.h>
+#include <hal/Ports.h>
+#include <wpi/SmallString.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/SensorUtil.h"
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+PowerDistributionPanel::PowerDistributionPanel() : PowerDistributionPanel(0) {}
+
+/**
+ * Initialize the PDP.
+ */
+PowerDistributionPanel::PowerDistributionPanel(int module) {
+ int32_t status = 0;
+ m_handle = HAL_InitializePDP(module, &status);
+ if (status != 0) {
+ wpi_setErrorWithContextRange(status, 0, HAL_GetNumPDPModules(), module,
+ HAL_GetErrorMessage(status));
+ return;
+ }
+
+ HAL_Report(HALUsageReporting::kResourceType_PDP, module);
+ SetName("PowerDistributionPanel", module);
+}
+
+double PowerDistributionPanel::GetVoltage() const {
+ int32_t status = 0;
+
+ double voltage = HAL_GetPDPVoltage(m_handle, &status);
+
+ if (status) {
+ wpi_setWPIErrorWithContext(Timeout, "");
+ }
+
+ return voltage;
+}
+
+double PowerDistributionPanel::GetTemperature() const {
+ int32_t status = 0;
+
+ double temperature = HAL_GetPDPTemperature(m_handle, &status);
+
+ if (status) {
+ wpi_setWPIErrorWithContext(Timeout, "");
+ }
+
+ return temperature;
+}
+
+double PowerDistributionPanel::GetCurrent(int channel) const {
+ int32_t status = 0;
+
+ if (!SensorUtil::CheckPDPChannel(channel)) {
+ wpi::SmallString<32> str;
+ wpi::raw_svector_ostream buf(str);
+ buf << "PDP Channel " << channel;
+ wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str());
+ }
+
+ double current = HAL_GetPDPChannelCurrent(m_handle, channel, &status);
+
+ if (status) {
+ wpi_setWPIErrorWithContext(Timeout, "");
+ }
+
+ return current;
+}
+
+double PowerDistributionPanel::GetTotalCurrent() const {
+ int32_t status = 0;
+
+ double current = HAL_GetPDPTotalCurrent(m_handle, &status);
+
+ if (status) {
+ wpi_setWPIErrorWithContext(Timeout, "");
+ }
+
+ return current;
+}
+
+double PowerDistributionPanel::GetTotalPower() const {
+ int32_t status = 0;
+
+ double power = HAL_GetPDPTotalPower(m_handle, &status);
+
+ if (status) {
+ wpi_setWPIErrorWithContext(Timeout, "");
+ }
+
+ return power;
+}
+
+double PowerDistributionPanel::GetTotalEnergy() const {
+ int32_t status = 0;
+
+ double energy = HAL_GetPDPTotalEnergy(m_handle, &status);
+
+ if (status) {
+ wpi_setWPIErrorWithContext(Timeout, "");
+ }
+
+ return energy;
+}
+
+void PowerDistributionPanel::ResetTotalEnergy() {
+ int32_t status = 0;
+
+ HAL_ResetPDPTotalEnergy(m_handle, &status);
+
+ if (status) {
+ wpi_setWPIErrorWithContext(Timeout, "");
+ }
+}
+
+void PowerDistributionPanel::ClearStickyFaults() {
+ int32_t status = 0;
+
+ HAL_ClearPDPStickyFaults(m_handle, &status);
+
+ if (status) {
+ wpi_setWPIErrorWithContext(Timeout, "");
+ }
+}
+
+void PowerDistributionPanel::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("PowerDistributionPanel");
+ for (int i = 0; i < SensorUtil::kPDPChannels; ++i) {
+ builder.AddDoubleProperty("Chan" + wpi::Twine(i),
+ [=]() { return GetCurrent(i); }, nullptr);
+ }
+ builder.AddDoubleProperty("Voltage", [=]() { return GetVoltage(); }, nullptr);
+ builder.AddDoubleProperty("TotalCurrent", [=]() { return GetTotalCurrent(); },
+ nullptr);
+}
diff --git a/wpilibc/src/main/native/cpp/Preferences.cpp b/wpilibc/src/main/native/cpp/Preferences.cpp
new file mode 100644
index 0000000..7a896d1
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Preferences.cpp
@@ -0,0 +1,114 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/Preferences.h"
+
+#include <algorithm>
+
+#include <hal/HAL.h>
+#include <networktables/NetworkTableInstance.h>
+#include <wpi/StringRef.h>
+
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+// The Preferences table name
+static wpi::StringRef kTableName{"Preferences"};
+
+Preferences* Preferences::GetInstance() {
+ static Preferences instance;
+ return &instance;
+}
+
+std::vector<std::string> Preferences::GetKeys() { return m_table->GetKeys(); }
+
+std::string Preferences::GetString(wpi::StringRef key,
+ wpi::StringRef defaultValue) {
+ return m_table->GetString(key, defaultValue);
+}
+
+int Preferences::GetInt(wpi::StringRef key, int defaultValue) {
+ return static_cast<int>(m_table->GetNumber(key, defaultValue));
+}
+
+double Preferences::GetDouble(wpi::StringRef key, double defaultValue) {
+ return m_table->GetNumber(key, defaultValue);
+}
+
+float Preferences::GetFloat(wpi::StringRef key, float defaultValue) {
+ return m_table->GetNumber(key, defaultValue);
+}
+
+bool Preferences::GetBoolean(wpi::StringRef key, bool defaultValue) {
+ return m_table->GetBoolean(key, defaultValue);
+}
+
+int64_t Preferences::GetLong(wpi::StringRef key, int64_t defaultValue) {
+ return static_cast<int64_t>(m_table->GetNumber(key, defaultValue));
+}
+
+void Preferences::PutString(wpi::StringRef key, wpi::StringRef value) {
+ auto entry = m_table->GetEntry(key);
+ entry.SetString(value);
+ entry.SetPersistent();
+}
+
+void Preferences::PutInt(wpi::StringRef key, int value) {
+ auto entry = m_table->GetEntry(key);
+ entry.SetDouble(value);
+ entry.SetPersistent();
+}
+
+void Preferences::PutDouble(wpi::StringRef key, double value) {
+ auto entry = m_table->GetEntry(key);
+ entry.SetDouble(value);
+ entry.SetPersistent();
+}
+
+void Preferences::PutFloat(wpi::StringRef key, float value) {
+ auto entry = m_table->GetEntry(key);
+ entry.SetDouble(value);
+ entry.SetPersistent();
+}
+
+void Preferences::PutBoolean(wpi::StringRef key, bool value) {
+ auto entry = m_table->GetEntry(key);
+ entry.SetBoolean(value);
+ entry.SetPersistent();
+}
+
+void Preferences::PutLong(wpi::StringRef key, int64_t value) {
+ auto entry = m_table->GetEntry(key);
+ entry.SetDouble(value);
+ entry.SetPersistent();
+}
+
+bool Preferences::ContainsKey(wpi::StringRef key) {
+ return m_table->ContainsKey(key);
+}
+
+void Preferences::Remove(wpi::StringRef key) { m_table->Delete(key); }
+
+void Preferences::RemoveAll() {
+ for (auto preference : GetKeys()) {
+ if (preference != ".type") {
+ Remove(preference);
+ }
+ }
+}
+
+Preferences::Preferences()
+ : m_table(nt::NetworkTableInstance::GetDefault().GetTable(kTableName)) {
+ m_table->GetEntry(".type").SetString("RobotPreferences");
+ m_listener = m_table->AddEntryListener(
+ [=](nt::NetworkTable* table, wpi::StringRef name,
+ nt::NetworkTableEntry entry, std::shared_ptr<nt::Value> value,
+ int flags) { entry.SetPersistent(); },
+ NT_NOTIFY_NEW | NT_NOTIFY_IMMEDIATE);
+ HAL_Report(HALUsageReporting::kResourceType_Preferences, 0);
+}
diff --git a/wpilibc/src/main/native/cpp/Relay.cpp b/wpilibc/src/main/native/cpp/Relay.cpp
new file mode 100644
index 0000000..9128d20
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Relay.cpp
@@ -0,0 +1,233 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Relay.h"
+
+#include <utility>
+
+#include <hal/HAL.h>
+#include <hal/Ports.h>
+#include <hal/Relay.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/SensorUtil.h"
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+Relay::Relay(int channel, Relay::Direction direction)
+ : m_channel(channel), m_direction(direction) {
+ if (!SensorUtil::CheckRelayChannel(m_channel)) {
+ wpi_setWPIErrorWithContext(ChannelIndexOutOfRange,
+ "Relay Channel " + wpi::Twine(m_channel));
+ return;
+ }
+
+ HAL_PortHandle portHandle = HAL_GetPort(channel);
+
+ if (m_direction == kBothDirections || m_direction == kForwardOnly) {
+ int32_t status = 0;
+ m_forwardHandle = HAL_InitializeRelayPort(portHandle, true, &status);
+ if (status != 0) {
+ wpi_setErrorWithContextRange(status, 0, HAL_GetNumRelayChannels(),
+ channel, HAL_GetErrorMessage(status));
+ m_forwardHandle = HAL_kInvalidHandle;
+ m_reverseHandle = HAL_kInvalidHandle;
+ return;
+ }
+ HAL_Report(HALUsageReporting::kResourceType_Relay, m_channel);
+ }
+ if (m_direction == kBothDirections || m_direction == kReverseOnly) {
+ int32_t status = 0;
+ m_reverseHandle = HAL_InitializeRelayPort(portHandle, false, &status);
+ if (status != 0) {
+ wpi_setErrorWithContextRange(status, 0, HAL_GetNumRelayChannels(),
+ channel, HAL_GetErrorMessage(status));
+ m_forwardHandle = HAL_kInvalidHandle;
+ m_reverseHandle = HAL_kInvalidHandle;
+ return;
+ }
+
+ HAL_Report(HALUsageReporting::kResourceType_Relay, m_channel + 128);
+ }
+
+ int32_t status = 0;
+ if (m_forwardHandle != HAL_kInvalidHandle) {
+ HAL_SetRelay(m_forwardHandle, false, &status);
+ if (status != 0) {
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ m_forwardHandle = HAL_kInvalidHandle;
+ m_reverseHandle = HAL_kInvalidHandle;
+ return;
+ }
+ }
+ if (m_reverseHandle != HAL_kInvalidHandle) {
+ HAL_SetRelay(m_reverseHandle, false, &status);
+ if (status != 0) {
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ m_forwardHandle = HAL_kInvalidHandle;
+ m_reverseHandle = HAL_kInvalidHandle;
+ return;
+ }
+ }
+
+ SetName("Relay", m_channel);
+}
+
+Relay::~Relay() {
+ int32_t status = 0;
+ HAL_SetRelay(m_forwardHandle, false, &status);
+ HAL_SetRelay(m_reverseHandle, false, &status);
+ // ignore errors, as we want to make sure a free happens.
+ if (m_forwardHandle != HAL_kInvalidHandle) HAL_FreeRelayPort(m_forwardHandle);
+ if (m_reverseHandle != HAL_kInvalidHandle) HAL_FreeRelayPort(m_reverseHandle);
+}
+
+Relay::Relay(Relay&& rhs)
+ : MotorSafety(std::move(rhs)),
+ SendableBase(std::move(rhs)),
+ m_channel(std::move(rhs.m_channel)),
+ m_direction(std::move(rhs.m_direction)) {
+ std::swap(m_forwardHandle, rhs.m_forwardHandle);
+ std::swap(m_reverseHandle, rhs.m_reverseHandle);
+}
+
+Relay& Relay::operator=(Relay&& rhs) {
+ MotorSafety::operator=(std::move(rhs));
+ SendableBase::operator=(std::move(rhs));
+
+ m_channel = std::move(rhs.m_channel);
+ m_direction = std::move(rhs.m_direction);
+ std::swap(m_forwardHandle, rhs.m_forwardHandle);
+ std::swap(m_reverseHandle, rhs.m_reverseHandle);
+
+ return *this;
+}
+
+void Relay::Set(Relay::Value value) {
+ if (StatusIsFatal()) return;
+
+ int32_t status = 0;
+
+ switch (value) {
+ case kOff:
+ if (m_direction == kBothDirections || m_direction == kForwardOnly) {
+ HAL_SetRelay(m_forwardHandle, false, &status);
+ }
+ if (m_direction == kBothDirections || m_direction == kReverseOnly) {
+ HAL_SetRelay(m_reverseHandle, false, &status);
+ }
+ break;
+ case kOn:
+ if (m_direction == kBothDirections || m_direction == kForwardOnly) {
+ HAL_SetRelay(m_forwardHandle, true, &status);
+ }
+ if (m_direction == kBothDirections || m_direction == kReverseOnly) {
+ HAL_SetRelay(m_reverseHandle, true, &status);
+ }
+ break;
+ case kForward:
+ if (m_direction == kReverseOnly) {
+ wpi_setWPIError(IncompatibleMode);
+ break;
+ }
+ if (m_direction == kBothDirections || m_direction == kForwardOnly) {
+ HAL_SetRelay(m_forwardHandle, true, &status);
+ }
+ if (m_direction == kBothDirections) {
+ HAL_SetRelay(m_reverseHandle, false, &status);
+ }
+ break;
+ case kReverse:
+ if (m_direction == kForwardOnly) {
+ wpi_setWPIError(IncompatibleMode);
+ break;
+ }
+ if (m_direction == kBothDirections) {
+ HAL_SetRelay(m_forwardHandle, false, &status);
+ }
+ if (m_direction == kBothDirections || m_direction == kReverseOnly) {
+ HAL_SetRelay(m_reverseHandle, true, &status);
+ }
+ break;
+ }
+
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+Relay::Value Relay::Get() const {
+ int32_t status;
+
+ if (m_direction == kForwardOnly) {
+ if (HAL_GetRelay(m_forwardHandle, &status)) {
+ return kOn;
+ } else {
+ return kOff;
+ }
+ } else if (m_direction == kReverseOnly) {
+ if (HAL_GetRelay(m_reverseHandle, &status)) {
+ return kOn;
+ } else {
+ return kOff;
+ }
+ } else {
+ if (HAL_GetRelay(m_forwardHandle, &status)) {
+ if (HAL_GetRelay(m_reverseHandle, &status)) {
+ return kOn;
+ } else {
+ return kForward;
+ }
+ } else {
+ if (HAL_GetRelay(m_reverseHandle, &status)) {
+ return kReverse;
+ } else {
+ return kOff;
+ }
+ }
+ }
+
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int Relay::GetChannel() const { return m_channel; }
+
+void Relay::StopMotor() { Set(kOff); }
+
+void Relay::GetDescription(wpi::raw_ostream& desc) const {
+ desc << "Relay " << GetChannel();
+}
+
+void Relay::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Relay");
+ builder.SetActuator(true);
+ builder.SetSafeState([=]() { Set(kOff); });
+ builder.AddSmallStringProperty(
+ "Value",
+ [=](wpi::SmallVectorImpl<char>& buf) -> wpi::StringRef {
+ switch (Get()) {
+ case kOn:
+ return "On";
+ case kForward:
+ return "Forward";
+ case kReverse:
+ return "Reverse";
+ default:
+ return "Off";
+ }
+ },
+ [=](wpi::StringRef value) {
+ if (value == "Off")
+ Set(kOff);
+ else if (value == "Forward")
+ Set(kForward);
+ else if (value == "Reverse")
+ Set(kReverse);
+ else if (value == "On")
+ Set(kOn);
+ });
+}
diff --git a/wpilibc/src/main/native/cpp/Resource.cpp b/wpilibc/src/main/native/cpp/Resource.cpp
new file mode 100644
index 0000000..e2c53d4
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Resource.cpp
@@ -0,0 +1,67 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Resource.h"
+
+#include "frc/ErrorBase.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+wpi::mutex Resource::m_createMutex;
+
+void Resource::CreateResourceObject(std::unique_ptr<Resource>& r,
+ uint32_t elements) {
+ std::lock_guard<wpi::mutex> lock(m_createMutex);
+ if (!r) {
+ r = std::make_unique<Resource>(elements);
+ }
+}
+
+Resource::Resource(uint32_t elements) {
+ m_isAllocated = std::vector<bool>(elements, false);
+}
+
+uint32_t Resource::Allocate(const std::string& resourceDesc) {
+ std::lock_guard<wpi::mutex> lock(m_allocateMutex);
+ for (uint32_t i = 0; i < m_isAllocated.size(); i++) {
+ if (!m_isAllocated[i]) {
+ m_isAllocated[i] = true;
+ return i;
+ }
+ }
+ wpi_setWPIErrorWithContext(NoAvailableResources, resourceDesc);
+ return std::numeric_limits<uint32_t>::max();
+}
+
+uint32_t Resource::Allocate(uint32_t index, const std::string& resourceDesc) {
+ std::lock_guard<wpi::mutex> lock(m_allocateMutex);
+ if (index >= m_isAllocated.size()) {
+ wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, resourceDesc);
+ return std::numeric_limits<uint32_t>::max();
+ }
+ if (m_isAllocated[index]) {
+ wpi_setWPIErrorWithContext(ResourceAlreadyAllocated, resourceDesc);
+ return std::numeric_limits<uint32_t>::max();
+ }
+ m_isAllocated[index] = true;
+ return index;
+}
+
+void Resource::Free(uint32_t index) {
+ std::unique_lock<wpi::mutex> lock(m_allocateMutex);
+ if (index == std::numeric_limits<uint32_t>::max()) return;
+ if (index >= m_isAllocated.size()) {
+ wpi_setWPIError(NotAllocated);
+ return;
+ }
+ if (!m_isAllocated[index]) {
+ wpi_setWPIError(NotAllocated);
+ return;
+ }
+ m_isAllocated[index] = false;
+}
diff --git a/wpilibc/src/main/native/cpp/RobotBase.cpp b/wpilibc/src/main/native/cpp/RobotBase.cpp
new file mode 100644
index 0000000..bc316f4
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/RobotBase.cpp
@@ -0,0 +1,125 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/RobotBase.h"
+
+#include <cstdio>
+
+#include <cameraserver/CameraServerShared.h>
+#include <cscore.h>
+#include <hal/HAL.h>
+#include <networktables/NetworkTableInstance.h>
+
+#include "WPILibVersion.h"
+#include "frc/DriverStation.h"
+#include "frc/RobotState.h"
+#include "frc/Utility.h"
+#include "frc/WPIErrors.h"
+#include "frc/livewindow/LiveWindow.h"
+#include "frc/smartdashboard/SmartDashboard.h"
+
+using namespace frc;
+
+int frc::RunHALInitialization() {
+ if (!HAL_Initialize(500, 0)) {
+ wpi::errs() << "FATAL ERROR: HAL could not be initialized\n";
+ return -1;
+ }
+ HAL_Report(HALUsageReporting::kResourceType_Language,
+ HALUsageReporting::kLanguage_CPlusPlus);
+ wpi::outs() << "\n********** Robot program starting **********\n";
+ return 0;
+}
+
+std::thread::id RobotBase::m_threadId;
+
+namespace {
+class WPILibCameraServerShared : public frc::CameraServerShared {
+ public:
+ void ReportUsbCamera(int id) override {
+ HAL_Report(HALUsageReporting::kResourceType_UsbCamera, id);
+ }
+ void ReportAxisCamera(int id) override {
+ HAL_Report(HALUsageReporting::kResourceType_AxisCamera, id);
+ }
+ void ReportVideoServer(int id) override {
+ HAL_Report(HALUsageReporting::kResourceType_PCVideoServer, id);
+ }
+ void SetCameraServerError(const wpi::Twine& error) override {
+ wpi_setGlobalWPIErrorWithContext(CameraServerError, error);
+ }
+ void SetVisionRunnerError(const wpi::Twine& error) override {
+ wpi_setGlobalErrorWithContext(-1, error);
+ }
+ void ReportDriverStationError(const wpi::Twine& error) override {
+ DriverStation::ReportError(error);
+ }
+ std::pair<std::thread::id, bool> GetRobotMainThreadId() const override {
+ return std::make_pair(RobotBase::GetThreadId(), true);
+ }
+};
+} // namespace
+
+static void SetupCameraServerShared() {
+ SetCameraServerShared(std::make_unique<WPILibCameraServerShared>());
+}
+
+bool RobotBase::IsEnabled() const { return m_ds.IsEnabled(); }
+
+bool RobotBase::IsDisabled() const { return m_ds.IsDisabled(); }
+
+bool RobotBase::IsAutonomous() const { return m_ds.IsAutonomous(); }
+
+bool RobotBase::IsOperatorControl() const { return m_ds.IsOperatorControl(); }
+
+bool RobotBase::IsTest() const { return m_ds.IsTest(); }
+
+bool RobotBase::IsNewDataAvailable() const { return m_ds.IsNewControlData(); }
+
+std::thread::id RobotBase::GetThreadId() { return m_threadId; }
+
+RobotBase::RobotBase() : m_ds(DriverStation::GetInstance()) {
+ if (!HAL_Initialize(500, 0)) {
+ wpi::errs() << "FATAL ERROR: HAL could not be initialized\n";
+ wpi::errs().flush();
+ std::terminate();
+ }
+ m_threadId = std::this_thread::get_id();
+
+ SetupCameraServerShared();
+
+ auto inst = nt::NetworkTableInstance::GetDefault();
+ inst.SetNetworkIdentity("Robot");
+ inst.StartServer("/home/lvuser/networktables.ini");
+
+ SmartDashboard::init();
+
+ if (IsReal()) {
+ std::FILE* file = nullptr;
+ file = std::fopen("/tmp/frc_versions/FRC_Lib_Version.ini", "w");
+
+ if (file != nullptr) {
+ std::fputs("C++ ", file);
+ std::fputs(GetWPILibVersion(), file);
+ std::fclose(file);
+ }
+ }
+
+ // First and one-time initialization
+ inst.GetTable("LiveWindow")
+ ->GetSubTable(".status")
+ ->GetEntry("LW Enabled")
+ .SetBoolean(false);
+
+ LiveWindow::GetInstance()->SetEnabled(false);
+}
+
+RobotBase::RobotBase(RobotBase&&) : m_ds(DriverStation::GetInstance()) {}
+
+RobotBase::~RobotBase() { cs::Shutdown(); }
+
+RobotBase& RobotBase::operator=(RobotBase&&) { return *this; }
diff --git a/wpilibc/src/main/native/cpp/RobotController.cpp b/wpilibc/src/main/native/cpp/RobotController.cpp
new file mode 100644
index 0000000..347440d
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/RobotController.cpp
@@ -0,0 +1,174 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/RobotController.h"
+
+#include <hal/HAL.h>
+
+#include "frc/ErrorBase.h"
+
+using namespace frc;
+
+int RobotController::GetFPGAVersion() {
+ int32_t status = 0;
+ int version = HAL_GetFPGAVersion(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return version;
+}
+
+int64_t RobotController::GetFPGARevision() {
+ int32_t status = 0;
+ int64_t revision = HAL_GetFPGARevision(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return revision;
+}
+
+uint64_t RobotController::GetFPGATime() {
+ int32_t status = 0;
+ uint64_t time = HAL_GetFPGATime(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return time;
+}
+
+bool RobotController::GetUserButton() {
+ int32_t status = 0;
+
+ bool value = HAL_GetFPGAButton(&status);
+ wpi_setGlobalError(status);
+
+ return value;
+}
+
+bool RobotController::IsSysActive() {
+ int32_t status = 0;
+ bool retVal = HAL_GetSystemActive(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+bool RobotController::IsBrownedOut() {
+ int32_t status = 0;
+ bool retVal = HAL_GetBrownedOut(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double RobotController::GetInputVoltage() {
+ int32_t status = 0;
+ double retVal = HAL_GetVinVoltage(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double RobotController::GetInputCurrent() {
+ int32_t status = 0;
+ double retVal = HAL_GetVinCurrent(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double RobotController::GetVoltage3V3() {
+ int32_t status = 0;
+ double retVal = HAL_GetUserVoltage3V3(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double RobotController::GetCurrent3V3() {
+ int32_t status = 0;
+ double retVal = HAL_GetUserCurrent3V3(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+bool RobotController::GetEnabled3V3() {
+ int32_t status = 0;
+ bool retVal = HAL_GetUserActive3V3(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+int RobotController::GetFaultCount3V3() {
+ int32_t status = 0;
+ int retVal = HAL_GetUserCurrentFaults3V3(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double RobotController::GetVoltage5V() {
+ int32_t status = 0;
+ double retVal = HAL_GetUserVoltage5V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double RobotController::GetCurrent5V() {
+ int32_t status = 0;
+ double retVal = HAL_GetUserCurrent5V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+bool RobotController::GetEnabled5V() {
+ int32_t status = 0;
+ bool retVal = HAL_GetUserActive5V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+int RobotController::GetFaultCount5V() {
+ int32_t status = 0;
+ int retVal = HAL_GetUserCurrentFaults5V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double RobotController::GetVoltage6V() {
+ int32_t status = 0;
+ double retVal = HAL_GetUserVoltage6V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+double RobotController::GetCurrent6V() {
+ int32_t status = 0;
+ double retVal = HAL_GetUserCurrent6V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+bool RobotController::GetEnabled6V() {
+ int32_t status = 0;
+ bool retVal = HAL_GetUserActive6V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+int RobotController::GetFaultCount6V() {
+ int32_t status = 0;
+ int retVal = HAL_GetUserCurrentFaults6V(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+CANStatus RobotController::GetCANStatus() {
+ int32_t status = 0;
+ float percentBusUtilization = 0;
+ uint32_t busOffCount = 0;
+ uint32_t txFullCount = 0;
+ uint32_t receiveErrorCount = 0;
+ uint32_t transmitErrorCount = 0;
+ HAL_CAN_GetCANStatus(&percentBusUtilization, &busOffCount, &txFullCount,
+ &receiveErrorCount, &transmitErrorCount, &status);
+ if (status != 0) {
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return {};
+ }
+ return {percentBusUtilization, static_cast<int>(busOffCount),
+ static_cast<int>(txFullCount), static_cast<int>(receiveErrorCount),
+ static_cast<int>(transmitErrorCount)};
+}
diff --git a/wpilibc/src/main/native/cpp/RobotDrive.cpp b/wpilibc/src/main/native/cpp/RobotDrive.cpp
new file mode 100644
index 0000000..a20eb65
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/RobotDrive.cpp
@@ -0,0 +1,427 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/RobotDrive.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include <hal/HAL.h>
+
+#include "frc/GenericHID.h"
+#include "frc/Joystick.h"
+#include "frc/Talon.h"
+#include "frc/Utility.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+static std::shared_ptr<SpeedController> make_shared_nodelete(
+ SpeedController* ptr) {
+ return std::shared_ptr<SpeedController>(ptr, NullDeleter<SpeedController>());
+}
+
+RobotDrive::RobotDrive(int leftMotorChannel, int rightMotorChannel) {
+ InitRobotDrive();
+ m_rearLeftMotor = std::make_shared<Talon>(leftMotorChannel);
+ m_rearRightMotor = std::make_shared<Talon>(rightMotorChannel);
+ SetLeftRightMotorOutputs(0.0, 0.0);
+}
+
+RobotDrive::RobotDrive(int frontLeftMotor, int rearLeftMotor,
+ int frontRightMotor, int rearRightMotor) {
+ InitRobotDrive();
+ m_rearLeftMotor = std::make_shared<Talon>(rearLeftMotor);
+ m_rearRightMotor = std::make_shared<Talon>(rearRightMotor);
+ m_frontLeftMotor = std::make_shared<Talon>(frontLeftMotor);
+ m_frontRightMotor = std::make_shared<Talon>(frontRightMotor);
+ SetLeftRightMotorOutputs(0.0, 0.0);
+}
+
+RobotDrive::RobotDrive(SpeedController* leftMotor,
+ SpeedController* rightMotor) {
+ InitRobotDrive();
+ if (leftMotor == nullptr || rightMotor == nullptr) {
+ wpi_setWPIError(NullParameter);
+ m_rearLeftMotor = m_rearRightMotor = nullptr;
+ return;
+ }
+ m_rearLeftMotor = make_shared_nodelete(leftMotor);
+ m_rearRightMotor = make_shared_nodelete(rightMotor);
+}
+
+RobotDrive::RobotDrive(SpeedController& leftMotor,
+ SpeedController& rightMotor) {
+ InitRobotDrive();
+ m_rearLeftMotor = make_shared_nodelete(&leftMotor);
+ m_rearRightMotor = make_shared_nodelete(&rightMotor);
+}
+
+RobotDrive::RobotDrive(std::shared_ptr<SpeedController> leftMotor,
+ std::shared_ptr<SpeedController> rightMotor) {
+ InitRobotDrive();
+ if (leftMotor == nullptr || rightMotor == nullptr) {
+ wpi_setWPIError(NullParameter);
+ m_rearLeftMotor = m_rearRightMotor = nullptr;
+ return;
+ }
+ m_rearLeftMotor = leftMotor;
+ m_rearRightMotor = rightMotor;
+}
+
+RobotDrive::RobotDrive(SpeedController* frontLeftMotor,
+ SpeedController* rearLeftMotor,
+ SpeedController* frontRightMotor,
+ SpeedController* rearRightMotor) {
+ InitRobotDrive();
+ if (frontLeftMotor == nullptr || rearLeftMotor == nullptr ||
+ frontRightMotor == nullptr || rearRightMotor == nullptr) {
+ wpi_setWPIError(NullParameter);
+ return;
+ }
+ m_frontLeftMotor = make_shared_nodelete(frontLeftMotor);
+ m_rearLeftMotor = make_shared_nodelete(rearLeftMotor);
+ m_frontRightMotor = make_shared_nodelete(frontRightMotor);
+ m_rearRightMotor = make_shared_nodelete(rearRightMotor);
+}
+
+RobotDrive::RobotDrive(SpeedController& frontLeftMotor,
+ SpeedController& rearLeftMotor,
+ SpeedController& frontRightMotor,
+ SpeedController& rearRightMotor) {
+ InitRobotDrive();
+ m_frontLeftMotor = make_shared_nodelete(&frontLeftMotor);
+ m_rearLeftMotor = make_shared_nodelete(&rearLeftMotor);
+ m_frontRightMotor = make_shared_nodelete(&frontRightMotor);
+ m_rearRightMotor = make_shared_nodelete(&rearRightMotor);
+}
+
+RobotDrive::RobotDrive(std::shared_ptr<SpeedController> frontLeftMotor,
+ std::shared_ptr<SpeedController> rearLeftMotor,
+ std::shared_ptr<SpeedController> frontRightMotor,
+ std::shared_ptr<SpeedController> rearRightMotor) {
+ InitRobotDrive();
+ if (frontLeftMotor == nullptr || rearLeftMotor == nullptr ||
+ frontRightMotor == nullptr || rearRightMotor == nullptr) {
+ wpi_setWPIError(NullParameter);
+ return;
+ }
+ m_frontLeftMotor = frontLeftMotor;
+ m_rearLeftMotor = rearLeftMotor;
+ m_frontRightMotor = frontRightMotor;
+ m_rearRightMotor = rearRightMotor;
+}
+
+void RobotDrive::Drive(double outputMagnitude, double curve) {
+ double leftOutput, rightOutput;
+ static bool reported = false;
+ if (!reported) {
+ HAL_Report(HALUsageReporting::kResourceType_RobotDrive, GetNumMotors(),
+ HALUsageReporting::kRobotDrive_ArcadeRatioCurve);
+ reported = true;
+ }
+
+ if (curve < 0) {
+ double value = std::log(-curve);
+ double ratio = (value - m_sensitivity) / (value + m_sensitivity);
+ if (ratio == 0) ratio = .0000000001;
+ leftOutput = outputMagnitude / ratio;
+ rightOutput = outputMagnitude;
+ } else if (curve > 0) {
+ double value = std::log(curve);
+ double ratio = (value - m_sensitivity) / (value + m_sensitivity);
+ if (ratio == 0) ratio = .0000000001;
+ leftOutput = outputMagnitude;
+ rightOutput = outputMagnitude / ratio;
+ } else {
+ leftOutput = outputMagnitude;
+ rightOutput = outputMagnitude;
+ }
+ SetLeftRightMotorOutputs(leftOutput, rightOutput);
+}
+
+void RobotDrive::TankDrive(GenericHID* leftStick, GenericHID* rightStick,
+ bool squaredInputs) {
+ if (leftStick == nullptr || rightStick == nullptr) {
+ wpi_setWPIError(NullParameter);
+ return;
+ }
+ TankDrive(leftStick->GetY(), rightStick->GetY(), squaredInputs);
+}
+
+void RobotDrive::TankDrive(GenericHID& leftStick, GenericHID& rightStick,
+ bool squaredInputs) {
+ TankDrive(leftStick.GetY(), rightStick.GetY(), squaredInputs);
+}
+
+void RobotDrive::TankDrive(GenericHID* leftStick, int leftAxis,
+ GenericHID* rightStick, int rightAxis,
+ bool squaredInputs) {
+ if (leftStick == nullptr || rightStick == nullptr) {
+ wpi_setWPIError(NullParameter);
+ return;
+ }
+ TankDrive(leftStick->GetRawAxis(leftAxis), rightStick->GetRawAxis(rightAxis),
+ squaredInputs);
+}
+
+void RobotDrive::TankDrive(GenericHID& leftStick, int leftAxis,
+ GenericHID& rightStick, int rightAxis,
+ bool squaredInputs) {
+ TankDrive(leftStick.GetRawAxis(leftAxis), rightStick.GetRawAxis(rightAxis),
+ squaredInputs);
+}
+
+void RobotDrive::TankDrive(double leftValue, double rightValue,
+ bool squaredInputs) {
+ static bool reported = false;
+ if (!reported) {
+ HAL_Report(HALUsageReporting::kResourceType_RobotDrive, GetNumMotors(),
+ HALUsageReporting::kRobotDrive_Tank);
+ reported = true;
+ }
+
+ leftValue = Limit(leftValue);
+ rightValue = Limit(rightValue);
+
+ // square the inputs (while preserving the sign) to increase fine control
+ // while permitting full power
+ if (squaredInputs) {
+ leftValue = std::copysign(leftValue * leftValue, leftValue);
+ rightValue = std::copysign(rightValue * rightValue, rightValue);
+ }
+
+ SetLeftRightMotorOutputs(leftValue, rightValue);
+}
+
+void RobotDrive::ArcadeDrive(GenericHID* stick, bool squaredInputs) {
+ // simply call the full-featured ArcadeDrive with the appropriate values
+ ArcadeDrive(stick->GetY(), stick->GetX(), squaredInputs);
+}
+
+void RobotDrive::ArcadeDrive(GenericHID& stick, bool squaredInputs) {
+ // simply call the full-featured ArcadeDrive with the appropriate values
+ ArcadeDrive(stick.GetY(), stick.GetX(), squaredInputs);
+}
+
+void RobotDrive::ArcadeDrive(GenericHID* moveStick, int moveAxis,
+ GenericHID* rotateStick, int rotateAxis,
+ bool squaredInputs) {
+ double moveValue = moveStick->GetRawAxis(moveAxis);
+ double rotateValue = rotateStick->GetRawAxis(rotateAxis);
+
+ ArcadeDrive(moveValue, rotateValue, squaredInputs);
+}
+
+void RobotDrive::ArcadeDrive(GenericHID& moveStick, int moveAxis,
+ GenericHID& rotateStick, int rotateAxis,
+ bool squaredInputs) {
+ double moveValue = moveStick.GetRawAxis(moveAxis);
+ double rotateValue = rotateStick.GetRawAxis(rotateAxis);
+
+ ArcadeDrive(moveValue, rotateValue, squaredInputs);
+}
+
+void RobotDrive::ArcadeDrive(double moveValue, double rotateValue,
+ bool squaredInputs) {
+ static bool reported = false;
+ if (!reported) {
+ HAL_Report(HALUsageReporting::kResourceType_RobotDrive, GetNumMotors(),
+ HALUsageReporting::kRobotDrive_ArcadeStandard);
+ reported = true;
+ }
+
+ // local variables to hold the computed PWM values for the motors
+ double leftMotorOutput;
+ double rightMotorOutput;
+
+ moveValue = Limit(moveValue);
+ rotateValue = Limit(rotateValue);
+
+ // square the inputs (while preserving the sign) to increase fine control
+ // while permitting full power
+ if (squaredInputs) {
+ moveValue = std::copysign(moveValue * moveValue, moveValue);
+ rotateValue = std::copysign(rotateValue * rotateValue, rotateValue);
+ }
+
+ if (moveValue > 0.0) {
+ if (rotateValue > 0.0) {
+ leftMotorOutput = moveValue - rotateValue;
+ rightMotorOutput = std::max(moveValue, rotateValue);
+ } else {
+ leftMotorOutput = std::max(moveValue, -rotateValue);
+ rightMotorOutput = moveValue + rotateValue;
+ }
+ } else {
+ if (rotateValue > 0.0) {
+ leftMotorOutput = -std::max(-moveValue, rotateValue);
+ rightMotorOutput = moveValue + rotateValue;
+ } else {
+ leftMotorOutput = moveValue - rotateValue;
+ rightMotorOutput = -std::max(-moveValue, -rotateValue);
+ }
+ }
+ SetLeftRightMotorOutputs(leftMotorOutput, rightMotorOutput);
+}
+
+void RobotDrive::MecanumDrive_Cartesian(double x, double y, double rotation,
+ double gyroAngle) {
+ static bool reported = false;
+ if (!reported) {
+ HAL_Report(HALUsageReporting::kResourceType_RobotDrive, GetNumMotors(),
+ HALUsageReporting::kRobotDrive_MecanumCartesian);
+ reported = true;
+ }
+
+ double xIn = x;
+ double yIn = y;
+ // Negate y for the joystick.
+ yIn = -yIn;
+ // Compenstate for gyro angle.
+ RotateVector(xIn, yIn, gyroAngle);
+
+ double wheelSpeeds[kMaxNumberOfMotors];
+ wheelSpeeds[kFrontLeftMotor] = xIn + yIn + rotation;
+ wheelSpeeds[kFrontRightMotor] = -xIn + yIn - rotation;
+ wheelSpeeds[kRearLeftMotor] = -xIn + yIn + rotation;
+ wheelSpeeds[kRearRightMotor] = xIn + yIn - rotation;
+
+ Normalize(wheelSpeeds);
+
+ m_frontLeftMotor->Set(wheelSpeeds[kFrontLeftMotor] * m_maxOutput);
+ m_frontRightMotor->Set(wheelSpeeds[kFrontRightMotor] * m_maxOutput);
+ m_rearLeftMotor->Set(wheelSpeeds[kRearLeftMotor] * m_maxOutput);
+ m_rearRightMotor->Set(wheelSpeeds[kRearRightMotor] * m_maxOutput);
+
+ Feed();
+}
+
+void RobotDrive::MecanumDrive_Polar(double magnitude, double direction,
+ double rotation) {
+ static bool reported = false;
+ if (!reported) {
+ HAL_Report(HALUsageReporting::kResourceType_RobotDrive, GetNumMotors(),
+ HALUsageReporting::kRobotDrive_MecanumPolar);
+ reported = true;
+ }
+
+ // Normalized for full power along the Cartesian axes.
+ magnitude = Limit(magnitude) * std::sqrt(2.0);
+ // The rollers are at 45 degree angles.
+ double dirInRad = (direction + 45.0) * 3.14159 / 180.0;
+ double cosD = std::cos(dirInRad);
+ double sinD = std::sin(dirInRad);
+
+ double wheelSpeeds[kMaxNumberOfMotors];
+ wheelSpeeds[kFrontLeftMotor] = sinD * magnitude + rotation;
+ wheelSpeeds[kFrontRightMotor] = cosD * magnitude - rotation;
+ wheelSpeeds[kRearLeftMotor] = cosD * magnitude + rotation;
+ wheelSpeeds[kRearRightMotor] = sinD * magnitude - rotation;
+
+ Normalize(wheelSpeeds);
+
+ m_frontLeftMotor->Set(wheelSpeeds[kFrontLeftMotor] * m_maxOutput);
+ m_frontRightMotor->Set(wheelSpeeds[kFrontRightMotor] * m_maxOutput);
+ m_rearLeftMotor->Set(wheelSpeeds[kRearLeftMotor] * m_maxOutput);
+ m_rearRightMotor->Set(wheelSpeeds[kRearRightMotor] * m_maxOutput);
+
+ Feed();
+}
+
+void RobotDrive::HolonomicDrive(double magnitude, double direction,
+ double rotation) {
+ MecanumDrive_Polar(magnitude, direction, rotation);
+}
+
+void RobotDrive::SetLeftRightMotorOutputs(double leftOutput,
+ double rightOutput) {
+ wpi_assert(m_rearLeftMotor != nullptr && m_rearRightMotor != nullptr);
+
+ if (m_frontLeftMotor != nullptr)
+ m_frontLeftMotor->Set(Limit(leftOutput) * m_maxOutput);
+ m_rearLeftMotor->Set(Limit(leftOutput) * m_maxOutput);
+
+ if (m_frontRightMotor != nullptr)
+ m_frontRightMotor->Set(-Limit(rightOutput) * m_maxOutput);
+ m_rearRightMotor->Set(-Limit(rightOutput) * m_maxOutput);
+
+ Feed();
+}
+
+void RobotDrive::SetInvertedMotor(MotorType motor, bool isInverted) {
+ if (motor < 0 || motor > 3) {
+ wpi_setWPIError(InvalidMotorIndex);
+ return;
+ }
+ switch (motor) {
+ case kFrontLeftMotor:
+ m_frontLeftMotor->SetInverted(isInverted);
+ break;
+ case kFrontRightMotor:
+ m_frontRightMotor->SetInverted(isInverted);
+ break;
+ case kRearLeftMotor:
+ m_rearLeftMotor->SetInverted(isInverted);
+ break;
+ case kRearRightMotor:
+ m_rearRightMotor->SetInverted(isInverted);
+ break;
+ }
+}
+
+void RobotDrive::SetSensitivity(double sensitivity) {
+ m_sensitivity = sensitivity;
+}
+
+void RobotDrive::SetMaxOutput(double maxOutput) { m_maxOutput = maxOutput; }
+
+void RobotDrive::GetDescription(wpi::raw_ostream& desc) const {
+ desc << "RobotDrive";
+}
+
+void RobotDrive::StopMotor() {
+ if (m_frontLeftMotor != nullptr) m_frontLeftMotor->StopMotor();
+ if (m_frontRightMotor != nullptr) m_frontRightMotor->StopMotor();
+ if (m_rearLeftMotor != nullptr) m_rearLeftMotor->StopMotor();
+ if (m_rearRightMotor != nullptr) m_rearRightMotor->StopMotor();
+ Feed();
+}
+
+void RobotDrive::InitRobotDrive() { SetSafetyEnabled(true); }
+
+double RobotDrive::Limit(double number) {
+ if (number > 1.0) {
+ return 1.0;
+ }
+ if (number < -1.0) {
+ return -1.0;
+ }
+ return number;
+}
+
+void RobotDrive::Normalize(double* wheelSpeeds) {
+ double maxMagnitude = std::fabs(wheelSpeeds[0]);
+ for (int i = 1; i < kMaxNumberOfMotors; i++) {
+ double temp = std::fabs(wheelSpeeds[i]);
+ if (maxMagnitude < temp) maxMagnitude = temp;
+ }
+ if (maxMagnitude > 1.0) {
+ for (int i = 0; i < kMaxNumberOfMotors; i++) {
+ wheelSpeeds[i] = wheelSpeeds[i] / maxMagnitude;
+ }
+ }
+}
+
+void RobotDrive::RotateVector(double& x, double& y, double angle) {
+ double cosA = std::cos(angle * (3.14159 / 180.0));
+ double sinA = std::sin(angle * (3.14159 / 180.0));
+ double xOut = x * cosA - y * sinA;
+ double yOut = x * sinA + y * cosA;
+ x = xOut;
+ y = yOut;
+}
diff --git a/wpilibc/src/main/native/cpp/RobotState.cpp b/wpilibc/src/main/native/cpp/RobotState.cpp
new file mode 100644
index 0000000..f5da5c1
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/RobotState.cpp
@@ -0,0 +1,30 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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 "frc/RobotState.h"
+
+#include "frc/DriverStation.h"
+
+using namespace frc;
+
+bool RobotState::IsDisabled() {
+ return DriverStation::GetInstance().IsDisabled();
+}
+
+bool RobotState::IsEnabled() {
+ return DriverStation::GetInstance().IsEnabled();
+}
+
+bool RobotState::IsOperatorControl() {
+ return DriverStation::GetInstance().IsOperatorControl();
+}
+
+bool RobotState::IsAutonomous() {
+ return DriverStation::GetInstance().IsAutonomous();
+}
+
+bool RobotState::IsTest() { return DriverStation::GetInstance().IsTest(); }
diff --git a/wpilibc/src/main/native/cpp/SD540.cpp b/wpilibc/src/main/native/cpp/SD540.cpp
new file mode 100644
index 0000000..977ae7b
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/SD540.cpp
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/SD540.h"
+
+#include <hal/HAL.h>
+
+using namespace frc;
+
+SD540::SD540(int channel) : PWMSpeedController(channel) {
+ /* Note that the SD540 uses the following bounds for PWM values. These values
+ * should work reasonably well for most controllers, but if users experience
+ * issues such as asymmetric behavior around the deadband or inability to
+ * saturate the controller in either direction, calibration is recommended.
+ * The calibration procedure can be found in the SD540 User Manual available
+ * from Mindsensors.
+ *
+ * 2.05ms = full "forward"
+ * 1.55ms = the "high end" of the deadband range
+ * 1.50ms = center of the deadband range (off)
+ * 1.44ms = the "low end" of the deadband range
+ * 0.94ms = full "reverse"
+ */
+ SetBounds(2.05, 1.55, 1.50, 1.44, .94);
+ SetPeriodMultiplier(kPeriodMultiplier_1X);
+ SetSpeed(0.0);
+ SetZeroLatch();
+
+ HAL_Report(HALUsageReporting::kResourceType_MindsensorsSD540, GetChannel());
+ SetName("SD540", GetChannel());
+}
diff --git a/wpilibc/src/main/native/cpp/SPI.cpp b/wpilibc/src/main/native/cpp/SPI.cpp
new file mode 100644
index 0000000..6b41adb
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/SPI.cpp
@@ -0,0 +1,442 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/SPI.h"
+
+#include <cstring>
+#include <utility>
+
+#include <hal/HAL.h>
+#include <hal/SPI.h>
+#include <wpi/SmallVector.h>
+#include <wpi/mutex.h>
+
+#include "frc/DigitalSource.h"
+#include "frc/Notifier.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+static constexpr int kAccumulateDepth = 2048;
+
+class SPI::Accumulator {
+ public:
+ Accumulator(HAL_SPIPort port, int xferSize, int validMask, int validValue,
+ int dataShift, int dataSize, bool isSigned, bool bigEndian)
+ : m_notifier([=]() {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ Update();
+ }),
+ m_buf(new uint32_t[(xferSize + 1) * kAccumulateDepth]),
+ m_validMask(validMask),
+ m_validValue(validValue),
+ m_dataMax(1 << dataSize),
+ m_dataMsbMask(1 << (dataSize - 1)),
+ m_dataShift(dataShift),
+ m_xferSize(xferSize + 1), // +1 for timestamp
+ m_isSigned(isSigned),
+ m_bigEndian(bigEndian),
+ m_port(port) {}
+ ~Accumulator() { delete[] m_buf; }
+
+ void Update();
+
+ Notifier m_notifier;
+ uint32_t* m_buf;
+ wpi::mutex m_mutex;
+
+ int64_t m_value = 0;
+ uint32_t m_count = 0;
+ int32_t m_lastValue = 0;
+ uint32_t m_lastTimestamp = 0;
+ double m_integratedValue = 0;
+
+ int32_t m_center = 0;
+ int32_t m_deadband = 0;
+ double m_integratedCenter = 0;
+
+ int32_t m_validMask;
+ int32_t m_validValue;
+ int32_t m_dataMax; // one more than max data value
+ int32_t m_dataMsbMask; // data field MSB mask (for signed)
+ uint8_t m_dataShift; // data field shift right amount, in bits
+ int32_t m_xferSize; // SPI transfer size, in bytes
+ bool m_isSigned; // is data field signed?
+ bool m_bigEndian; // is response big endian?
+ HAL_SPIPort m_port;
+};
+
+void SPI::Accumulator::Update() {
+ bool done;
+ do {
+ done = true;
+ int32_t status = 0;
+
+ // get amount of data available
+ int32_t numToRead =
+ HAL_ReadSPIAutoReceivedData(m_port, m_buf, 0, 0, &status);
+ if (status != 0) return; // error reading
+
+ // only get whole responses; +1 is for timestamp
+ numToRead -= numToRead % m_xferSize;
+ if (numToRead > m_xferSize * kAccumulateDepth) {
+ numToRead = m_xferSize * kAccumulateDepth;
+ done = false;
+ }
+ if (numToRead == 0) return; // no samples
+
+ // read buffered data
+ HAL_ReadSPIAutoReceivedData(m_port, m_buf, numToRead, 0, &status);
+ if (status != 0) return; // error reading
+
+ // loop over all responses
+ for (int32_t off = 0; off < numToRead; off += m_xferSize) {
+ // get timestamp from first word
+ uint32_t timestamp = m_buf[off];
+
+ // convert from bytes
+ uint32_t resp = 0;
+ if (m_bigEndian) {
+ for (int32_t i = 1; i < m_xferSize; ++i) {
+ resp <<= 8;
+ resp |= m_buf[off + i] & 0xff;
+ }
+ } else {
+ for (int32_t i = m_xferSize - 1; i >= 1; --i) {
+ resp <<= 8;
+ resp |= m_buf[off + i] & 0xff;
+ }
+ }
+
+ // process response
+ if ((resp & m_validMask) == static_cast<uint32_t>(m_validValue)) {
+ // valid sensor data; extract data field
+ int32_t data = static_cast<int32_t>(resp >> m_dataShift);
+ data &= m_dataMax - 1;
+ // 2s complement conversion if signed MSB is set
+ if (m_isSigned && (data & m_dataMsbMask) != 0) data -= m_dataMax;
+ // center offset
+ int32_t dataNoCenter = data;
+ data -= m_center;
+ // only accumulate if outside deadband
+ if (data < -m_deadband || data > m_deadband) {
+ m_value += data;
+ if (m_count != 0) {
+ // timestamps use the 1us FPGA clock; also handle rollover
+ if (timestamp >= m_lastTimestamp)
+ m_integratedValue +=
+ dataNoCenter *
+ static_cast<int32_t>(timestamp - m_lastTimestamp) * 1e-6 -
+ m_integratedCenter;
+ else
+ m_integratedValue +=
+ dataNoCenter *
+ static_cast<int32_t>((1ULL << 32) - m_lastTimestamp +
+ timestamp) *
+ 1e-6 -
+ m_integratedCenter;
+ }
+ }
+ ++m_count;
+ m_lastValue = data;
+ } else {
+ // no data from the sensor; just clear the last value
+ m_lastValue = 0;
+ }
+ m_lastTimestamp = timestamp;
+ }
+ } while (!done);
+}
+
+SPI::SPI(Port port) : m_port(static_cast<HAL_SPIPort>(port)) {
+ int32_t status = 0;
+ HAL_InitializeSPI(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ static int instances = 0;
+ instances++;
+ HAL_Report(HALUsageReporting::kResourceType_SPI, instances);
+}
+
+SPI::~SPI() { HAL_CloseSPI(m_port); }
+
+SPI::SPI(SPI&& rhs)
+ : ErrorBase(std::move(rhs)),
+ m_msbFirst(std::move(rhs.m_msbFirst)),
+ m_sampleOnTrailing(std::move(rhs.m_sampleOnTrailing)),
+ m_clockIdleHigh(std::move(rhs.m_clockIdleHigh)),
+ m_accum(std::move(rhs.m_accum)) {
+ std::swap(m_port, rhs.m_port);
+}
+
+SPI& SPI::operator=(SPI&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+
+ std::swap(m_port, rhs.m_port);
+ m_msbFirst = std::move(rhs.m_msbFirst);
+ m_sampleOnTrailing = std::move(rhs.m_sampleOnTrailing);
+ m_clockIdleHigh = std::move(rhs.m_clockIdleHigh);
+ m_accum = std::move(rhs.m_accum);
+
+ return *this;
+}
+
+void SPI::SetClockRate(double hz) { HAL_SetSPISpeed(m_port, hz); }
+
+void SPI::SetMSBFirst() {
+ m_msbFirst = true;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+}
+
+void SPI::SetLSBFirst() {
+ m_msbFirst = false;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+}
+
+void SPI::SetSampleDataOnLeadingEdge() {
+ m_sampleOnTrailing = false;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+}
+
+void SPI::SetSampleDataOnTrailingEdge() {
+ m_sampleOnTrailing = true;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+}
+
+void SPI::SetSampleDataOnFalling() {
+ m_sampleOnTrailing = true;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+}
+
+void SPI::SetSampleDataOnRising() {
+ m_sampleOnTrailing = false;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+}
+
+void SPI::SetClockActiveLow() {
+ m_clockIdleHigh = true;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+}
+
+void SPI::SetClockActiveHigh() {
+ m_clockIdleHigh = false;
+ HAL_SetSPIOpts(m_port, m_msbFirst, m_sampleOnTrailing, m_clockIdleHigh);
+}
+
+void SPI::SetChipSelectActiveHigh() {
+ int32_t status = 0;
+ HAL_SetSPIChipSelectActiveHigh(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SPI::SetChipSelectActiveLow() {
+ int32_t status = 0;
+ HAL_SetSPIChipSelectActiveLow(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int SPI::Write(uint8_t* data, int size) {
+ int retVal = 0;
+ retVal = HAL_WriteSPI(m_port, data, size);
+ return retVal;
+}
+
+int SPI::Read(bool initiate, uint8_t* dataReceived, int size) {
+ int retVal = 0;
+ if (initiate) {
+ wpi::SmallVector<uint8_t, 32> dataToSend;
+ dataToSend.resize(size);
+ retVal = HAL_TransactionSPI(m_port, dataToSend.data(), dataReceived, size);
+ } else {
+ retVal = HAL_ReadSPI(m_port, dataReceived, size);
+ }
+ return retVal;
+}
+
+int SPI::Transaction(uint8_t* dataToSend, uint8_t* dataReceived, int size) {
+ int retVal = 0;
+ retVal = HAL_TransactionSPI(m_port, dataToSend, dataReceived, size);
+ return retVal;
+}
+
+void SPI::InitAuto(int bufferSize) {
+ int32_t status = 0;
+ HAL_InitSPIAuto(m_port, bufferSize, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SPI::FreeAuto() {
+ int32_t status = 0;
+ HAL_FreeSPIAuto(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SPI::SetAutoTransmitData(wpi::ArrayRef<uint8_t> dataToSend, int zeroSize) {
+ int32_t status = 0;
+ HAL_SetSPIAutoTransmitData(m_port, dataToSend.data(), dataToSend.size(),
+ zeroSize, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SPI::StartAutoRate(double period) {
+ int32_t status = 0;
+ HAL_StartSPIAutoRate(m_port, period, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SPI::StartAutoTrigger(DigitalSource& source, bool rising, bool falling) {
+ int32_t status = 0;
+ HAL_StartSPIAutoTrigger(
+ m_port, source.GetPortHandleForRouting(),
+ (HAL_AnalogTriggerType)source.GetAnalogTriggerTypeForRouting(), rising,
+ falling, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SPI::StopAuto() {
+ int32_t status = 0;
+ HAL_StopSPIAuto(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SPI::ForceAutoRead() {
+ int32_t status = 0;
+ HAL_ForceSPIAutoRead(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int SPI::ReadAutoReceivedData(uint32_t* buffer, int numToRead, double timeout) {
+ int32_t status = 0;
+ int32_t val =
+ HAL_ReadSPIAutoReceivedData(m_port, buffer, numToRead, timeout, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return val;
+}
+
+int SPI::GetAutoDroppedCount() {
+ int32_t status = 0;
+ int32_t val = HAL_GetSPIAutoDroppedCount(m_port, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return val;
+}
+
+void SPI::InitAccumulator(double period, int cmd, int xferSize, int validMask,
+ int validValue, int dataShift, int dataSize,
+ bool isSigned, bool bigEndian) {
+ InitAuto(xferSize * kAccumulateDepth);
+ uint8_t cmdBytes[4] = {0, 0, 0, 0};
+ if (bigEndian) {
+ for (int32_t i = xferSize - 1; i >= 0; --i) {
+ cmdBytes[i] = cmd & 0xff;
+ cmd >>= 8;
+ }
+ } else {
+ cmdBytes[0] = cmd & 0xff;
+ cmd >>= 8;
+ cmdBytes[1] = cmd & 0xff;
+ cmd >>= 8;
+ cmdBytes[2] = cmd & 0xff;
+ cmd >>= 8;
+ cmdBytes[3] = cmd & 0xff;
+ }
+ SetAutoTransmitData(cmdBytes, xferSize - 4);
+ StartAutoRate(period);
+
+ m_accum.reset(new Accumulator(m_port, xferSize, validMask, validValue,
+ dataShift, dataSize, isSigned, bigEndian));
+ m_accum->m_notifier.StartPeriodic(period * kAccumulateDepth / 2);
+}
+
+void SPI::FreeAccumulator() {
+ m_accum.reset(nullptr);
+ FreeAuto();
+}
+
+void SPI::ResetAccumulator() {
+ if (!m_accum) return;
+ std::lock_guard<wpi::mutex> lock(m_accum->m_mutex);
+ m_accum->m_value = 0;
+ m_accum->m_count = 0;
+ m_accum->m_lastValue = 0;
+ m_accum->m_lastTimestamp = 0;
+ m_accum->m_integratedValue = 0;
+}
+
+void SPI::SetAccumulatorCenter(int center) {
+ if (!m_accum) return;
+ std::lock_guard<wpi::mutex> lock(m_accum->m_mutex);
+ m_accum->m_center = center;
+}
+
+void SPI::SetAccumulatorDeadband(int deadband) {
+ if (!m_accum) return;
+ std::lock_guard<wpi::mutex> lock(m_accum->m_mutex);
+ m_accum->m_deadband = deadband;
+}
+
+int SPI::GetAccumulatorLastValue() const {
+ if (!m_accum) return 0;
+ std::lock_guard<wpi::mutex> lock(m_accum->m_mutex);
+ m_accum->Update();
+ return m_accum->m_lastValue;
+}
+
+int64_t SPI::GetAccumulatorValue() const {
+ if (!m_accum) return 0;
+ std::lock_guard<wpi::mutex> lock(m_accum->m_mutex);
+ m_accum->Update();
+ return m_accum->m_value;
+}
+
+int64_t SPI::GetAccumulatorCount() const {
+ if (!m_accum) return 0;
+ std::lock_guard<wpi::mutex> lock(m_accum->m_mutex);
+ m_accum->Update();
+ return m_accum->m_count;
+}
+
+double SPI::GetAccumulatorAverage() const {
+ if (!m_accum) return 0;
+ std::lock_guard<wpi::mutex> lock(m_accum->m_mutex);
+ m_accum->Update();
+ if (m_accum->m_count == 0) return 0.0;
+ return static_cast<double>(m_accum->m_value) / m_accum->m_count;
+}
+
+void SPI::GetAccumulatorOutput(int64_t& value, int64_t& count) const {
+ if (!m_accum) {
+ value = 0;
+ count = 0;
+ return;
+ }
+ std::lock_guard<wpi::mutex> lock(m_accum->m_mutex);
+ m_accum->Update();
+ value = m_accum->m_value;
+ count = m_accum->m_count;
+}
+
+void SPI::SetAccumulatorIntegratedCenter(double center) {
+ if (!m_accum) return;
+ std::lock_guard<wpi::mutex> lock(m_accum->m_mutex);
+ m_accum->m_integratedCenter = center;
+}
+
+double SPI::GetAccumulatorIntegratedValue() const {
+ if (!m_accum) return 0;
+ std::lock_guard<wpi::mutex> lock(m_accum->m_mutex);
+ m_accum->Update();
+ return m_accum->m_integratedValue;
+}
+
+double SPI::GetAccumulatorIntegratedAverage() const {
+ if (!m_accum) return 0;
+ std::lock_guard<wpi::mutex> lock(m_accum->m_mutex);
+ m_accum->Update();
+ if (m_accum->m_count <= 1) return 0.0;
+ // count-1 due to not integrating the first value received
+ return m_accum->m_integratedValue / (m_accum->m_count - 1);
+}
diff --git a/wpilibc/src/main/native/cpp/SampleRobot.cpp b/wpilibc/src/main/native/cpp/SampleRobot.cpp
new file mode 100644
index 0000000..338f7be
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/SampleRobot.cpp
@@ -0,0 +1,86 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/SampleRobot.h"
+
+#include <hal/DriverStation.h>
+#include <hal/FRCUsageReporting.h>
+#include <hal/HALBase.h>
+#include <networktables/NetworkTable.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/DriverStation.h"
+#include "frc/Timer.h"
+#include "frc/livewindow/LiveWindow.h"
+
+using namespace frc;
+
+void SampleRobot::StartCompetition() {
+ LiveWindow* lw = LiveWindow::GetInstance();
+
+ RobotInit();
+
+ // Tell the DS that the robot is ready to be enabled
+ HAL_ObserveUserProgramStarting();
+
+ RobotMain();
+
+ if (!m_robotMainOverridden) {
+ while (true) {
+ if (IsDisabled()) {
+ m_ds.InDisabled(true);
+ Disabled();
+ m_ds.InDisabled(false);
+ while (IsDisabled()) m_ds.WaitForData();
+ } else if (IsAutonomous()) {
+ m_ds.InAutonomous(true);
+ Autonomous();
+ m_ds.InAutonomous(false);
+ while (IsAutonomous() && IsEnabled()) m_ds.WaitForData();
+ } else if (IsTest()) {
+ lw->SetEnabled(true);
+ m_ds.InTest(true);
+ Test();
+ m_ds.InTest(false);
+ while (IsTest() && IsEnabled()) m_ds.WaitForData();
+ lw->SetEnabled(false);
+ } else {
+ m_ds.InOperatorControl(true);
+ OperatorControl();
+ m_ds.InOperatorControl(false);
+ while (IsOperatorControl() && IsEnabled()) m_ds.WaitForData();
+ }
+ }
+ }
+}
+
+void SampleRobot::RobotInit() {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+}
+
+void SampleRobot::Disabled() {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+}
+
+void SampleRobot::Autonomous() {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+}
+
+void SampleRobot::OperatorControl() {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+}
+
+void SampleRobot::Test() {
+ wpi::outs() << "Default " << __FUNCTION__ << "() method... Overload me!\n";
+}
+
+void SampleRobot::RobotMain() { m_robotMainOverridden = false; }
+
+SampleRobot::SampleRobot() {
+ HAL_Report(HALUsageReporting::kResourceType_Framework,
+ HALUsageReporting::kFramework_Simple);
+}
diff --git a/wpilibc/src/main/native/cpp/SensorUtil.cpp b/wpilibc/src/main/native/cpp/SensorUtil.cpp
new file mode 100644
index 0000000..2012da4
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/SensorUtil.cpp
@@ -0,0 +1,66 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/SensorUtil.h"
+
+#include <hal/AnalogInput.h>
+#include <hal/AnalogOutput.h>
+#include <hal/DIO.h>
+#include <hal/HAL.h>
+#include <hal/PDP.h>
+#include <hal/PWM.h>
+#include <hal/Ports.h>
+#include <hal/Relay.h>
+#include <hal/Solenoid.h>
+
+using namespace frc;
+
+const int SensorUtil::kDigitalChannels = HAL_GetNumDigitalChannels();
+const int SensorUtil::kAnalogInputs = HAL_GetNumAnalogInputs();
+const int SensorUtil::kSolenoidChannels = HAL_GetNumSolenoidChannels();
+const int SensorUtil::kSolenoidModules = HAL_GetNumPCMModules();
+const int SensorUtil::kPwmChannels = HAL_GetNumPWMChannels();
+const int SensorUtil::kRelayChannels = HAL_GetNumRelayHeaders();
+const int SensorUtil::kPDPChannels = HAL_GetNumPDPChannels();
+
+int SensorUtil::GetDefaultSolenoidModule() { return 0; }
+
+bool SensorUtil::CheckSolenoidModule(int moduleNumber) {
+ return HAL_CheckSolenoidModule(moduleNumber);
+}
+
+bool SensorUtil::CheckDigitalChannel(int channel) {
+ return HAL_CheckDIOChannel(channel);
+}
+
+bool SensorUtil::CheckRelayChannel(int channel) {
+ return HAL_CheckRelayChannel(channel);
+}
+
+bool SensorUtil::CheckPWMChannel(int channel) {
+ return HAL_CheckPWMChannel(channel);
+}
+
+bool SensorUtil::CheckAnalogInputChannel(int channel) {
+ return HAL_CheckAnalogInputChannel(channel);
+}
+
+bool SensorUtil::CheckAnalogOutputChannel(int channel) {
+ return HAL_CheckAnalogOutputChannel(channel);
+}
+
+bool SensorUtil::CheckSolenoidChannel(int channel) {
+ return HAL_CheckSolenoidChannel(channel);
+}
+
+bool SensorUtil::CheckPDPChannel(int channel) {
+ return HAL_CheckPDPChannel(channel);
+}
+
+bool SensorUtil::CheckPDPModule(int module) {
+ return HAL_CheckPDPModule(module);
+}
diff --git a/wpilibc/src/main/native/cpp/SerialPort.cpp b/wpilibc/src/main/native/cpp/SerialPort.cpp
new file mode 100644
index 0000000..a399f4d
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/SerialPort.cpp
@@ -0,0 +1,203 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/SerialPort.h"
+
+#include <utility>
+
+#include <hal/HAL.h>
+#include <hal/SerialPort.h>
+
+// static ViStatus _VI_FUNCH ioCompleteHandler (ViSession vi, ViEventType
+// eventType, ViEvent event, ViAddr userHandle);
+
+using namespace frc;
+
+SerialPort::SerialPort(int baudRate, Port port, int dataBits,
+ SerialPort::Parity parity,
+ SerialPort::StopBits stopBits) {
+ int32_t status = 0;
+
+ m_port = port;
+
+ HAL_InitializeSerialPort(static_cast<HAL_SerialPort>(port), &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ // Don't continue if initialization failed
+ if (status < 0) return;
+ HAL_SetSerialBaudRate(static_cast<HAL_SerialPort>(port), baudRate, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_SetSerialDataBits(static_cast<HAL_SerialPort>(port), dataBits, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_SetSerialParity(static_cast<HAL_SerialPort>(port), parity, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_SetSerialStopBits(static_cast<HAL_SerialPort>(port), stopBits, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ // Set the default timeout to 5 seconds.
+ SetTimeout(5.0);
+
+ // Don't wait until the buffer is full to transmit.
+ SetWriteBufferMode(kFlushOnAccess);
+
+ EnableTermination();
+
+ // viInstallHandler(m_portHandle, VI_EVENT_IO_COMPLETION, ioCompleteHandler,
+ // this);
+ // viEnableEvent(m_portHandle, VI_EVENT_IO_COMPLETION, VI_HNDLR, VI_NULL);
+
+ HAL_Report(HALUsageReporting::kResourceType_SerialPort, 0);
+}
+
+SerialPort::SerialPort(int baudRate, const wpi::Twine& portName, Port port,
+ int dataBits, SerialPort::Parity parity,
+ SerialPort::StopBits stopBits) {
+ int32_t status = 0;
+
+ m_port = port;
+
+ wpi::SmallVector<char, 64> buf;
+ const char* portNameC = portName.toNullTerminatedStringRef(buf).data();
+
+ HAL_InitializeSerialPortDirect(static_cast<HAL_SerialPort>(port), portNameC,
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ // Don't continue if initialization failed
+ if (status < 0) return;
+ HAL_SetSerialBaudRate(static_cast<HAL_SerialPort>(port), baudRate, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_SetSerialDataBits(static_cast<HAL_SerialPort>(port), dataBits, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_SetSerialParity(static_cast<HAL_SerialPort>(port), parity, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_SetSerialStopBits(static_cast<HAL_SerialPort>(port), stopBits, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ // Set the default timeout to 5 seconds.
+ SetTimeout(5.0);
+
+ // Don't wait until the buffer is full to transmit.
+ SetWriteBufferMode(kFlushOnAccess);
+
+ EnableTermination();
+
+ // viInstallHandler(m_portHandle, VI_EVENT_IO_COMPLETION, ioCompleteHandler,
+ // this);
+ // viEnableEvent(m_portHandle, VI_EVENT_IO_COMPLETION, VI_HNDLR, VI_NULL);
+
+ HAL_Report(HALUsageReporting::kResourceType_SerialPort, 0);
+}
+
+SerialPort::~SerialPort() {
+ int32_t status = 0;
+ HAL_CloseSerial(static_cast<HAL_SerialPort>(m_port), &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+SerialPort::SerialPort(SerialPort&& rhs)
+ : ErrorBase(std::move(rhs)),
+ m_resourceManagerHandle(std::move(rhs.m_resourceManagerHandle)),
+ m_portHandle(std::move(rhs.m_portHandle)),
+ m_consoleModeEnabled(std::move(rhs.m_consoleModeEnabled)) {
+ std::swap(m_port, rhs.m_port);
+}
+
+SerialPort& SerialPort::operator=(SerialPort&& rhs) {
+ ErrorBase::operator=(std::move(rhs));
+
+ m_resourceManagerHandle = std::move(rhs.m_resourceManagerHandle);
+ m_portHandle = std::move(rhs.m_portHandle);
+ m_consoleModeEnabled = std::move(rhs.m_consoleModeEnabled);
+ std::swap(m_port, rhs.m_port);
+
+ return *this;
+}
+
+void SerialPort::SetFlowControl(SerialPort::FlowControl flowControl) {
+ int32_t status = 0;
+ HAL_SetSerialFlowControl(static_cast<HAL_SerialPort>(m_port), flowControl,
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SerialPort::EnableTermination(char terminator) {
+ int32_t status = 0;
+ HAL_EnableSerialTermination(static_cast<HAL_SerialPort>(m_port), terminator,
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SerialPort::DisableTermination() {
+ int32_t status = 0;
+ HAL_DisableSerialTermination(static_cast<HAL_SerialPort>(m_port), &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+int SerialPort::GetBytesReceived() {
+ int32_t status = 0;
+ int retVal =
+ HAL_GetSerialBytesReceived(static_cast<HAL_SerialPort>(m_port), &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+int SerialPort::Read(char* buffer, int count) {
+ int32_t status = 0;
+ int retVal = HAL_ReadSerial(static_cast<HAL_SerialPort>(m_port), buffer,
+ count, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+int SerialPort::Write(const char* buffer, int count) {
+ return Write(wpi::StringRef(buffer, static_cast<size_t>(count)));
+}
+
+int SerialPort::Write(wpi::StringRef buffer) {
+ int32_t status = 0;
+ int retVal = HAL_WriteSerial(static_cast<HAL_SerialPort>(m_port),
+ buffer.data(), buffer.size(), &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return retVal;
+}
+
+void SerialPort::SetTimeout(double timeout) {
+ int32_t status = 0;
+ HAL_SetSerialTimeout(static_cast<HAL_SerialPort>(m_port), timeout, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SerialPort::SetReadBufferSize(int size) {
+ int32_t status = 0;
+ HAL_SetSerialReadBufferSize(static_cast<HAL_SerialPort>(m_port), size,
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SerialPort::SetWriteBufferSize(int size) {
+ int32_t status = 0;
+ HAL_SetSerialWriteBufferSize(static_cast<HAL_SerialPort>(m_port), size,
+ &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SerialPort::SetWriteBufferMode(SerialPort::WriteBufferMode mode) {
+ int32_t status = 0;
+ HAL_SetSerialWriteMode(static_cast<HAL_SerialPort>(m_port), mode, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SerialPort::Flush() {
+ int32_t status = 0;
+ HAL_FlushSerial(static_cast<HAL_SerialPort>(m_port), &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void SerialPort::Reset() {
+ int32_t status = 0;
+ HAL_ClearSerial(static_cast<HAL_SerialPort>(m_port), &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
diff --git a/wpilibc/src/main/native/cpp/Servo.cpp b/wpilibc/src/main/native/cpp/Servo.cpp
new file mode 100644
index 0000000..b4c9eb5
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Servo.cpp
@@ -0,0 +1,65 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Servo.h"
+
+#include <hal/HAL.h>
+
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+constexpr double Servo::kMaxServoAngle;
+constexpr double Servo::kMinServoAngle;
+
+constexpr double Servo::kDefaultMaxServoPWM;
+constexpr double Servo::kDefaultMinServoPWM;
+
+Servo::Servo(int channel) : PWM(channel) {
+ // Set minimum and maximum PWM values supported by the servo
+ SetBounds(kDefaultMaxServoPWM, 0.0, 0.0, 0.0, kDefaultMinServoPWM);
+
+ // Assign defaults for period multiplier for the servo PWM control signal
+ SetPeriodMultiplier(kPeriodMultiplier_4X);
+
+ HAL_Report(HALUsageReporting::kResourceType_Servo, channel);
+ SetName("Servo", channel);
+}
+
+void Servo::Set(double value) { SetPosition(value); }
+
+void Servo::SetOffline() { SetRaw(0); }
+
+double Servo::Get() const { return GetPosition(); }
+
+void Servo::SetAngle(double degrees) {
+ if (degrees < kMinServoAngle) {
+ degrees = kMinServoAngle;
+ } else if (degrees > kMaxServoAngle) {
+ degrees = kMaxServoAngle;
+ }
+
+ SetPosition((degrees - kMinServoAngle) / GetServoAngleRange());
+}
+
+double Servo::GetAngle() const {
+ return GetPosition() * GetServoAngleRange() + kMinServoAngle;
+}
+
+double Servo::GetMaxAngle() const { return kMaxServoAngle; }
+
+double Servo::GetMinAngle() const { return kMinServoAngle; }
+
+void Servo::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Servo");
+ builder.AddDoubleProperty("Value", [=]() { return Get(); },
+ [=](double value) { Set(value); });
+}
+
+double Servo::GetServoAngleRange() const {
+ return kMaxServoAngle - kMinServoAngle;
+}
diff --git a/wpilibc/src/main/native/cpp/Solenoid.cpp b/wpilibc/src/main/native/cpp/Solenoid.cpp
new file mode 100644
index 0000000..3445f5d
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Solenoid.cpp
@@ -0,0 +1,110 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Solenoid.h"
+
+#include <utility>
+
+#include <hal/HAL.h>
+#include <hal/Ports.h>
+#include <hal/Solenoid.h>
+
+#include "frc/SensorUtil.h"
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+Solenoid::Solenoid(int channel)
+ : Solenoid(SensorUtil::GetDefaultSolenoidModule(), channel) {}
+
+Solenoid::Solenoid(int moduleNumber, int channel)
+ : SolenoidBase(moduleNumber), m_channel(channel) {
+ if (!SensorUtil::CheckSolenoidModule(m_moduleNumber)) {
+ wpi_setWPIErrorWithContext(ModuleIndexOutOfRange,
+ "Solenoid Module " + wpi::Twine(m_moduleNumber));
+ return;
+ }
+ if (!SensorUtil::CheckSolenoidChannel(m_channel)) {
+ wpi_setWPIErrorWithContext(ChannelIndexOutOfRange,
+ "Solenoid Channel " + wpi::Twine(m_channel));
+ return;
+ }
+
+ int32_t status = 0;
+ m_solenoidHandle = HAL_InitializeSolenoidPort(
+ HAL_GetPortWithModule(moduleNumber, channel), &status);
+ if (status != 0) {
+ wpi_setErrorWithContextRange(status, 0, HAL_GetNumSolenoidChannels(),
+ channel, HAL_GetErrorMessage(status));
+ m_solenoidHandle = HAL_kInvalidHandle;
+ return;
+ }
+
+ HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_channel,
+ m_moduleNumber);
+ SetName("Solenoid", m_moduleNumber, m_channel);
+}
+
+Solenoid::~Solenoid() { HAL_FreeSolenoidPort(m_solenoidHandle); }
+
+Solenoid::Solenoid(Solenoid&& rhs)
+ : SolenoidBase(std::move(rhs)), m_channel(std::move(rhs.m_channel)) {
+ std::swap(m_solenoidHandle, rhs.m_solenoidHandle);
+}
+
+Solenoid& Solenoid::operator=(Solenoid&& rhs) {
+ SolenoidBase::operator=(std::move(rhs));
+
+ std::swap(m_solenoidHandle, rhs.m_solenoidHandle);
+ m_channel = std::move(rhs.m_channel);
+
+ return *this;
+}
+
+void Solenoid::Set(bool on) {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetSolenoid(m_solenoidHandle, on, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+bool Solenoid::Get() const {
+ if (StatusIsFatal()) return false;
+ int32_t status = 0;
+ bool value = HAL_GetSolenoid(m_solenoidHandle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+bool Solenoid::IsBlackListed() const {
+ int value = GetPCMSolenoidBlackList(m_moduleNumber) & (1 << m_channel);
+ return (value != 0);
+}
+
+void Solenoid::SetPulseDuration(double durationSeconds) {
+ int32_t durationMS = durationSeconds * 1000;
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_SetOneShotDuration(m_solenoidHandle, durationMS, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Solenoid::StartPulse() {
+ if (StatusIsFatal()) return;
+ int32_t status = 0;
+ HAL_FireOneShot(m_solenoidHandle, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
+
+void Solenoid::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Solenoid");
+ builder.SetActuator(true);
+ builder.SetSafeState([=]() { Set(false); });
+ builder.AddBooleanProperty("Value", [=]() { return Get(); },
+ [=](bool value) { Set(value); });
+}
diff --git a/wpilibc/src/main/native/cpp/SolenoidBase.cpp b/wpilibc/src/main/native/cpp/SolenoidBase.cpp
new file mode 100644
index 0000000..c0b79a5
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/SolenoidBase.cpp
@@ -0,0 +1,63 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/SolenoidBase.h"
+
+#include <hal/HAL.h>
+#include <hal/Solenoid.h>
+
+using namespace frc;
+
+int SolenoidBase::GetAll(int module) {
+ int value = 0;
+ int32_t status = 0;
+ value = HAL_GetAllSolenoids(module, &status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return value;
+}
+
+int SolenoidBase::GetAll() const {
+ return SolenoidBase::GetAll(m_moduleNumber);
+}
+
+int SolenoidBase::GetPCMSolenoidBlackList(int module) {
+ int32_t status = 0;
+ return HAL_GetPCMSolenoidBlackList(module, &status);
+}
+
+int SolenoidBase::GetPCMSolenoidBlackList() const {
+ return SolenoidBase::GetPCMSolenoidBlackList(m_moduleNumber);
+}
+
+bool SolenoidBase::GetPCMSolenoidVoltageStickyFault(int module) {
+ int32_t status = 0;
+ return HAL_GetPCMSolenoidVoltageStickyFault(module, &status);
+}
+
+bool SolenoidBase::GetPCMSolenoidVoltageStickyFault() const {
+ return SolenoidBase::GetPCMSolenoidVoltageStickyFault(m_moduleNumber);
+}
+
+bool SolenoidBase::GetPCMSolenoidVoltageFault(int module) {
+ int32_t status = 0;
+ return HAL_GetPCMSolenoidVoltageFault(module, &status);
+}
+
+bool SolenoidBase::GetPCMSolenoidVoltageFault() const {
+ return SolenoidBase::GetPCMSolenoidVoltageFault(m_moduleNumber);
+}
+
+void SolenoidBase::ClearAllPCMStickyFaults(int module) {
+ int32_t status = 0;
+ return HAL_ClearAllPCMStickyFaults(module, &status);
+}
+
+void SolenoidBase::ClearAllPCMStickyFaults() {
+ SolenoidBase::ClearAllPCMStickyFaults(m_moduleNumber);
+}
+
+SolenoidBase::SolenoidBase(int moduleNumber) : m_moduleNumber(moduleNumber) {}
diff --git a/wpilibc/src/main/native/cpp/Spark.cpp b/wpilibc/src/main/native/cpp/Spark.cpp
new file mode 100644
index 0000000..fcfcb96
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Spark.cpp
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Spark.h"
+
+#include <hal/HAL.h>
+
+using namespace frc;
+
+Spark::Spark(int channel) : PWMSpeedController(channel) {
+ /* Note that the Spark uses the following bounds for PWM values. These values
+ * should work reasonably well for most controllers, but if users experience
+ * issues such as asymmetric behavior around the deadband or inability to
+ * saturate the controller in either direction, calibration is recommended.
+ * The calibration procedure can be found in the Spark User Manual available
+ * from REV Robotics.
+ *
+ * 2.003ms = full "forward"
+ * 1.55ms = the "high end" of the deadband range
+ * 1.50ms = center of the deadband range (off)
+ * 1.46ms = the "low end" of the deadband range
+ * 0.999ms = full "reverse"
+ */
+ SetBounds(2.003, 1.55, 1.50, 1.46, .999);
+ SetPeriodMultiplier(kPeriodMultiplier_1X);
+ SetSpeed(0.0);
+ SetZeroLatch();
+
+ HAL_Report(HALUsageReporting::kResourceType_RevSPARK, GetChannel());
+ SetName("Spark", GetChannel());
+}
diff --git a/wpilibc/src/main/native/cpp/SpeedControllerGroup.cpp b/wpilibc/src/main/native/cpp/SpeedControllerGroup.cpp
new file mode 100644
index 0000000..a807afc
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/SpeedControllerGroup.cpp
@@ -0,0 +1,53 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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 "frc/SpeedControllerGroup.h"
+
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+void SpeedControllerGroup::Set(double speed) {
+ for (auto speedController : m_speedControllers) {
+ speedController.get().Set(m_isInverted ? -speed : speed);
+ }
+}
+
+double SpeedControllerGroup::Get() const {
+ if (!m_speedControllers.empty()) {
+ return m_speedControllers.front().get().Get() * (m_isInverted ? -1 : 1);
+ }
+ return 0.0;
+}
+
+void SpeedControllerGroup::SetInverted(bool isInverted) {
+ m_isInverted = isInverted;
+}
+
+bool SpeedControllerGroup::GetInverted() const { return m_isInverted; }
+
+void SpeedControllerGroup::Disable() {
+ for (auto speedController : m_speedControllers) {
+ speedController.get().Disable();
+ }
+}
+
+void SpeedControllerGroup::StopMotor() {
+ for (auto speedController : m_speedControllers) {
+ speedController.get().StopMotor();
+ }
+}
+
+void SpeedControllerGroup::PIDWrite(double output) { Set(output); }
+
+void SpeedControllerGroup::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Speed Controller");
+ builder.SetActuator(true);
+ builder.SetSafeState([=]() { StopMotor(); });
+ builder.AddDoubleProperty("Value", [=]() { return Get(); },
+ [=](double value) { Set(value); });
+}
diff --git a/wpilibc/src/main/native/cpp/Talon.cpp b/wpilibc/src/main/native/cpp/Talon.cpp
new file mode 100644
index 0000000..34f659a
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Talon.cpp
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Talon.h"
+
+#include <hal/HAL.h>
+
+using namespace frc;
+
+Talon::Talon(int channel) : PWMSpeedController(channel) {
+ /* Note that the Talon uses the following bounds for PWM values. These values
+ * should work reasonably well for most controllers, but if users experience
+ * issues such as asymmetric behavior around the deadband or inability to
+ * saturate the controller in either direction, calibration is recommended.
+ * The calibration procedure can be found in the Talon User Manual available
+ * from CTRE.
+ *
+ * 2.037ms = full "forward"
+ * 1.539ms = the "high end" of the deadband range
+ * 1.513ms = center of the deadband range (off)
+ * 1.487ms = the "low end" of the deadband range
+ * 0.989ms = full "reverse"
+ */
+ SetBounds(2.037, 1.539, 1.513, 1.487, .989);
+ SetPeriodMultiplier(kPeriodMultiplier_1X);
+ SetSpeed(0.0);
+ SetZeroLatch();
+
+ HAL_Report(HALUsageReporting::kResourceType_Talon, GetChannel());
+ SetName("Talon", GetChannel());
+}
diff --git a/wpilibc/src/main/native/cpp/Threads.cpp b/wpilibc/src/main/native/cpp/Threads.cpp
new file mode 100644
index 0000000..7713f66
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Threads.cpp
@@ -0,0 +1,49 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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 "frc/Threads.h"
+
+#include <hal/HAL.h>
+#include <hal/Threads.h>
+
+#include "frc/ErrorBase.h"
+
+using namespace frc;
+
+int GetThreadPriority(std::thread& thread, bool* isRealTime) {
+ int32_t status = 0;
+ HAL_Bool rt = false;
+ auto native = thread.native_handle();
+ auto ret = HAL_GetThreadPriority(&native, &rt, &status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ *isRealTime = rt;
+ return ret;
+}
+
+int GetCurrentThreadPriority(bool* isRealTime) {
+ int32_t status = 0;
+ HAL_Bool rt = false;
+ auto ret = HAL_GetCurrentThreadPriority(&rt, &status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ *isRealTime = rt;
+ return ret;
+}
+
+bool SetThreadPriority(std::thread& thread, bool realTime, int priority) {
+ int32_t status = 0;
+ auto native = thread.native_handle();
+ auto ret = HAL_SetThreadPriority(&native, realTime, priority, &status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return ret;
+}
+
+bool SetCurrentThreadPriority(bool realTime, int priority) {
+ int32_t status = 0;
+ auto ret = HAL_SetCurrentThreadPriority(realTime, priority, &status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return ret;
+}
diff --git a/wpilibc/src/main/native/cpp/TimedRobot.cpp b/wpilibc/src/main/native/cpp/TimedRobot.cpp
new file mode 100644
index 0000000..24ab668
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/TimedRobot.cpp
@@ -0,0 +1,87 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/TimedRobot.h"
+
+#include <stdint.h>
+
+#include <utility>
+
+#include <hal/HAL.h>
+
+#include "frc/Timer.h"
+#include "frc/Utility.h"
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+void TimedRobot::StartCompetition() {
+ RobotInit();
+
+ // Tell the DS that the robot is ready to be enabled
+ HAL_ObserveUserProgramStarting();
+
+ m_expirationTime = Timer::GetFPGATimestamp() + m_period;
+ UpdateAlarm();
+
+ // Loop forever, calling the appropriate mode-dependent function
+ while (true) {
+ int32_t status = 0;
+ uint64_t curTime = HAL_WaitForNotifierAlarm(m_notifier, &status);
+ if (curTime == 0 || status != 0) break;
+
+ m_expirationTime += m_period;
+
+ UpdateAlarm();
+
+ // Call callback
+ LoopFunc();
+ }
+}
+
+double TimedRobot::GetPeriod() const { return m_period; }
+
+TimedRobot::TimedRobot(double period) : IterativeRobotBase(period) {
+ int32_t status = 0;
+ m_notifier = HAL_InitializeNotifier(&status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ HAL_Report(HALUsageReporting::kResourceType_Framework,
+ HALUsageReporting::kFramework_Timed);
+}
+
+TimedRobot::~TimedRobot() {
+ int32_t status = 0;
+
+ HAL_StopNotifier(m_notifier, &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ HAL_CleanNotifier(m_notifier, &status);
+}
+
+TimedRobot::TimedRobot(TimedRobot&& rhs)
+ : IterativeRobotBase(std::move(rhs)),
+ m_expirationTime(std::move(rhs.m_expirationTime)) {
+ std::swap(m_notifier, rhs.m_notifier);
+}
+
+TimedRobot& TimedRobot::operator=(TimedRobot&& rhs) {
+ IterativeRobotBase::operator=(std::move(rhs));
+ ErrorBase::operator=(std::move(rhs));
+
+ std::swap(m_notifier, rhs.m_notifier);
+ m_expirationTime = std::move(rhs.m_expirationTime);
+
+ return *this;
+}
+
+void TimedRobot::UpdateAlarm() {
+ int32_t status = 0;
+ HAL_UpdateNotifierAlarm(
+ m_notifier, static_cast<uint64_t>(m_expirationTime * 1e6), &status);
+ wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+}
diff --git a/wpilibc/src/main/native/cpp/Timer.cpp b/wpilibc/src/main/native/cpp/Timer.cpp
new file mode 100644
index 0000000..ae4a66e
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Timer.cpp
@@ -0,0 +1,107 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Timer.h"
+
+#include <chrono>
+#include <thread>
+
+#include <hal/HAL.h>
+
+#include "frc/DriverStation.h"
+#include "frc/RobotController.h"
+
+namespace frc {
+
+void Wait(double seconds) {
+ std::this_thread::sleep_for(std::chrono::duration<double>(seconds));
+}
+
+double GetClock() { return Timer::GetFPGATimestamp(); }
+
+double GetTime() {
+ using std::chrono::duration;
+ using std::chrono::duration_cast;
+ using std::chrono::system_clock;
+
+ return duration_cast<duration<double>>(system_clock::now().time_since_epoch())
+ .count();
+}
+
+} // namespace frc
+
+using namespace frc;
+
+// for compatibility with msvc12--see C2864
+const double Timer::kRolloverTime = (1ll << 32) / 1e6;
+
+Timer::Timer() { Reset(); }
+
+double Timer::Get() const {
+ double result;
+ double currentTime = GetFPGATimestamp();
+
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ if (m_running) {
+ // If the current time is before the start time, then the FPGA clock rolled
+ // over. Compensate by adding the ~71 minutes that it takes to roll over to
+ // the current time.
+ if (currentTime < m_startTime) {
+ currentTime += kRolloverTime;
+ }
+
+ result = (currentTime - m_startTime) + m_accumulatedTime;
+ } else {
+ result = m_accumulatedTime;
+ }
+
+ return result;
+}
+
+void Timer::Reset() {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ m_accumulatedTime = 0;
+ m_startTime = GetFPGATimestamp();
+}
+
+void Timer::Start() {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ if (!m_running) {
+ m_startTime = GetFPGATimestamp();
+ m_running = true;
+ }
+}
+
+void Timer::Stop() {
+ double temp = Get();
+
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ if (m_running) {
+ m_accumulatedTime = temp;
+ m_running = false;
+ }
+}
+
+bool Timer::HasPeriodPassed(double period) {
+ if (Get() > period) {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ // Advance the start time by the period.
+ m_startTime += period;
+ // Don't set it to the current time... we want to avoid drift.
+ return true;
+ }
+ return false;
+}
+
+double Timer::GetFPGATimestamp() {
+ // FPGA returns the timestamp in microseconds
+ return RobotController::GetFPGATime() * 1.0e-6;
+}
+
+double Timer::GetMatchTime() {
+ return DriverStation::GetInstance().GetMatchTime();
+}
diff --git a/wpilibc/src/main/native/cpp/Ultrasonic.cpp b/wpilibc/src/main/native/cpp/Ultrasonic.cpp
new file mode 100644
index 0000000..ee4f5cc
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Ultrasonic.cpp
@@ -0,0 +1,207 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Ultrasonic.h"
+
+#include <hal/HAL.h>
+
+#include "frc/Counter.h"
+#include "frc/DigitalInput.h"
+#include "frc/DigitalOutput.h"
+#include "frc/Timer.h"
+#include "frc/Utility.h"
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+// Automatic round robin mode
+std::atomic<bool> Ultrasonic::m_automaticEnabled{false};
+
+std::vector<Ultrasonic*> Ultrasonic::m_sensors;
+std::thread Ultrasonic::m_thread;
+
+Ultrasonic::Ultrasonic(int pingChannel, int echoChannel, DistanceUnit units)
+ : m_pingChannel(std::make_shared<DigitalOutput>(pingChannel)),
+ m_echoChannel(std::make_shared<DigitalInput>(echoChannel)),
+ m_counter(m_echoChannel) {
+ m_units = units;
+ Initialize();
+ AddChild(m_pingChannel);
+ AddChild(m_echoChannel);
+}
+
+Ultrasonic::Ultrasonic(DigitalOutput* pingChannel, DigitalInput* echoChannel,
+ DistanceUnit units)
+ : m_pingChannel(pingChannel, NullDeleter<DigitalOutput>()),
+ m_echoChannel(echoChannel, NullDeleter<DigitalInput>()),
+ m_counter(m_echoChannel) {
+ if (pingChannel == nullptr || echoChannel == nullptr) {
+ wpi_setWPIError(NullParameter);
+ m_units = units;
+ return;
+ }
+ m_units = units;
+ Initialize();
+}
+
+Ultrasonic::Ultrasonic(DigitalOutput& pingChannel, DigitalInput& echoChannel,
+ DistanceUnit units)
+ : m_pingChannel(&pingChannel, NullDeleter<DigitalOutput>()),
+ m_echoChannel(&echoChannel, NullDeleter<DigitalInput>()),
+ m_counter(m_echoChannel) {
+ m_units = units;
+ Initialize();
+}
+
+Ultrasonic::Ultrasonic(std::shared_ptr<DigitalOutput> pingChannel,
+ std::shared_ptr<DigitalInput> echoChannel,
+ DistanceUnit units)
+ : m_pingChannel(pingChannel),
+ m_echoChannel(echoChannel),
+ m_counter(m_echoChannel) {
+ m_units = units;
+ Initialize();
+}
+
+Ultrasonic::~Ultrasonic() {
+ // Delete the instance of the ultrasonic sensor by freeing the allocated
+ // digital channels. If the system was in automatic mode (round robin), then
+ // it is stopped, then started again after this sensor is removed (provided
+ // this wasn't the last sensor).
+
+ bool wasAutomaticMode = m_automaticEnabled;
+ SetAutomaticMode(false);
+
+ // No synchronization needed because the background task is stopped.
+ m_sensors.erase(std::remove(m_sensors.begin(), m_sensors.end(), this),
+ m_sensors.end());
+
+ if (!m_sensors.empty() && wasAutomaticMode) {
+ SetAutomaticMode(true);
+ }
+}
+
+void Ultrasonic::Ping() {
+ wpi_assert(!m_automaticEnabled);
+
+ // Reset the counter to zero (invalid data now)
+ m_counter.Reset();
+
+ // Do the ping to start getting a single range
+ m_pingChannel->Pulse(kPingTime);
+}
+
+bool Ultrasonic::IsRangeValid() const { return m_counter.Get() > 1; }
+
+void Ultrasonic::SetAutomaticMode(bool enabling) {
+ if (enabling == m_automaticEnabled) return; // ignore the case of no change
+
+ m_automaticEnabled = enabling;
+
+ if (enabling) {
+ /* Clear all the counters so no data is valid. No synchronization is needed
+ * because the background task is stopped.
+ */
+ for (auto& sensor : m_sensors) {
+ sensor->m_counter.Reset();
+ }
+
+ m_thread = std::thread(&Ultrasonic::UltrasonicChecker);
+
+ // TODO: Currently, lvuser does not have permissions to set task priorities.
+ // Until that is the case, uncommenting this will break user code that calls
+ // Ultrasonic::SetAutomicMode().
+ // m_task.SetPriority(kPriority);
+ } else {
+ // Wait for background task to stop running
+ if (m_thread.joinable()) {
+ m_thread.join();
+ }
+
+ // Clear all the counters (data now invalid) since automatic mode is
+ // disabled. No synchronization is needed because the background task is
+ // stopped.
+ for (auto& sensor : m_sensors) {
+ sensor->m_counter.Reset();
+ }
+ }
+}
+
+double Ultrasonic::GetRangeInches() const {
+ if (IsRangeValid())
+ return m_counter.GetPeriod() * kSpeedOfSoundInchesPerSec / 2.0;
+ else
+ return 0;
+}
+
+double Ultrasonic::GetRangeMM() const { return GetRangeInches() * 25.4; }
+
+bool Ultrasonic::IsEnabled() const { return m_enabled; }
+
+void Ultrasonic::SetEnabled(bool enable) { m_enabled = enable; }
+
+void Ultrasonic::SetDistanceUnits(DistanceUnit units) { m_units = units; }
+
+Ultrasonic::DistanceUnit Ultrasonic::GetDistanceUnits() const {
+ return m_units;
+}
+
+double Ultrasonic::PIDGet() {
+ switch (m_units) {
+ case Ultrasonic::kInches:
+ return GetRangeInches();
+ case Ultrasonic::kMilliMeters:
+ return GetRangeMM();
+ default:
+ return 0.0;
+ }
+}
+
+void Ultrasonic::SetPIDSourceType(PIDSourceType pidSource) {
+ if (wpi_assert(pidSource == PIDSourceType::kDisplacement)) {
+ m_pidSource = pidSource;
+ }
+}
+
+void Ultrasonic::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Ultrasonic");
+ builder.AddDoubleProperty("Value", [=]() { return GetRangeInches(); },
+ nullptr);
+}
+
+void Ultrasonic::Initialize() {
+ bool originalMode = m_automaticEnabled;
+ SetAutomaticMode(false); // Kill task when adding a new sensor
+ // Link this instance on the list
+ m_sensors.emplace_back(this);
+
+ m_counter.SetMaxPeriod(1.0);
+ m_counter.SetSemiPeriodMode(true);
+ m_counter.Reset();
+ m_enabled = true; // Make it available for round robin scheduling
+ SetAutomaticMode(originalMode);
+
+ static int instances = 0;
+ instances++;
+ HAL_Report(HALUsageReporting::kResourceType_Ultrasonic, instances);
+ SetName("Ultrasonic", m_echoChannel->GetChannel());
+}
+
+void Ultrasonic::UltrasonicChecker() {
+ while (m_automaticEnabled) {
+ for (auto& sensor : m_sensors) {
+ if (!m_automaticEnabled) break;
+
+ if (sensor->IsEnabled()) {
+ sensor->m_pingChannel->Pulse(kPingTime); // do the ping
+ }
+
+ Wait(0.1); // wait for ping to return
+ }
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/Utility.cpp b/wpilibc/src/main/native/cpp/Utility.cpp
new file mode 100644
index 0000000..503b6d0
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Utility.cpp
@@ -0,0 +1,203 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Utility.h"
+
+#ifndef _WIN32
+#include <cxxabi.h>
+#include <execinfo.h>
+#endif
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <hal/DriverStation.h>
+#include <hal/HAL.h>
+#include <wpi/Path.h>
+#include <wpi/SmallString.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/ErrorBase.h"
+
+using namespace frc;
+
+bool wpi_assert_impl(bool conditionValue, const wpi::Twine& conditionText,
+ const wpi::Twine& message, wpi::StringRef fileName,
+ int lineNumber, wpi::StringRef funcName) {
+ if (!conditionValue) {
+ wpi::SmallString<128> locBuf;
+ wpi::raw_svector_ostream locStream(locBuf);
+ locStream << funcName << " [" << wpi::sys::path::filename(fileName) << ":"
+ << lineNumber << "]";
+
+ wpi::SmallString<128> errorBuf;
+ wpi::raw_svector_ostream errorStream(errorBuf);
+
+ errorStream << "Assertion \"" << conditionText << "\" ";
+
+ if (message.isTriviallyEmpty() ||
+ (message.isSingleStringRef() && message.getSingleStringRef().empty())) {
+ errorStream << "failed.\n";
+ } else {
+ errorStream << "failed: " << message << "\n";
+ }
+
+ std::string stack = GetStackTrace(2);
+
+ // Print the error and send it to the DriverStation
+ HAL_SendError(1, 1, 0, errorBuf.c_str(), locBuf.c_str(), stack.c_str(), 1);
+ }
+
+ return conditionValue;
+}
+
+/**
+ * Common error routines for wpi_assertEqual_impl and wpi_assertNotEqual_impl.
+ *
+ * This should not be called directly; it should only be used by
+ * wpi_assertEqual_impl and wpi_assertNotEqual_impl.
+ */
+void wpi_assertEqual_common_impl(const wpi::Twine& valueA,
+ const wpi::Twine& valueB,
+ const wpi::Twine& equalityType,
+ const wpi::Twine& message,
+ wpi::StringRef fileName, int lineNumber,
+ wpi::StringRef funcName) {
+ wpi::SmallString<128> locBuf;
+ wpi::raw_svector_ostream locStream(locBuf);
+ locStream << funcName << " [" << wpi::sys::path::filename(fileName) << ":"
+ << lineNumber << "]";
+
+ wpi::SmallString<128> errorBuf;
+ wpi::raw_svector_ostream errorStream(errorBuf);
+
+ errorStream << "Assertion \"" << valueA << " " << equalityType << " "
+ << valueB << "\" ";
+
+ if (message.isTriviallyEmpty() ||
+ (message.isSingleStringRef() && message.getSingleStringRef().empty())) {
+ errorStream << "failed.\n";
+ } else {
+ errorStream << "failed: " << message << "\n";
+ }
+
+ std::string trace = GetStackTrace(3);
+
+ // Print the error and send it to the DriverStation
+ HAL_SendError(1, 1, 0, errorBuf.c_str(), locBuf.c_str(), trace.c_str(), 1);
+}
+
+bool wpi_assertEqual_impl(int valueA, int valueB,
+ const wpi::Twine& valueAString,
+ const wpi::Twine& valueBString,
+ const wpi::Twine& message, wpi::StringRef fileName,
+ int lineNumber, wpi::StringRef funcName) {
+ if (!(valueA == valueB)) {
+ wpi_assertEqual_common_impl(valueAString, valueBString, "==", message,
+ fileName, lineNumber, funcName);
+ }
+ return valueA == valueB;
+}
+
+bool wpi_assertNotEqual_impl(int valueA, int valueB,
+ const wpi::Twine& valueAString,
+ const wpi::Twine& valueBString,
+ const wpi::Twine& message, wpi::StringRef fileName,
+ int lineNumber, wpi::StringRef funcName) {
+ if (!(valueA != valueB)) {
+ wpi_assertEqual_common_impl(valueAString, valueBString, "!=", message,
+ fileName, lineNumber, funcName);
+ }
+ return valueA != valueB;
+}
+
+namespace frc {
+
+int GetFPGAVersion() {
+ int32_t status = 0;
+ int version = HAL_GetFPGAVersion(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return version;
+}
+
+int64_t GetFPGARevision() {
+ int32_t status = 0;
+ int64_t revision = HAL_GetFPGARevision(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return revision;
+}
+
+uint64_t GetFPGATime() {
+ int32_t status = 0;
+ uint64_t time = HAL_GetFPGATime(&status);
+ wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ return time;
+}
+
+bool GetUserButton() {
+ int32_t status = 0;
+
+ bool value = HAL_GetFPGAButton(&status);
+ wpi_setGlobalError(status);
+
+ return value;
+}
+
+#ifndef _WIN32
+
+/**
+ * Demangle a C++ symbol, used for printing stack traces.
+ */
+static std::string demangle(char const* mangledSymbol) {
+ char buffer[256];
+ size_t length;
+ int32_t status;
+
+ if (std::sscanf(mangledSymbol, "%*[^(]%*[(]%255[^)+]", buffer)) {
+ char* symbol = abi::__cxa_demangle(buffer, nullptr, &length, &status);
+ if (status == 0) {
+ return symbol;
+ } else {
+ // If the symbol couldn't be demangled, it's probably a C function,
+ // so just return it as-is.
+ return buffer;
+ }
+ }
+
+ // If everything else failed, just return the mangled symbol
+ return mangledSymbol;
+}
+
+std::string GetStackTrace(int offset) {
+ void* stackTrace[128];
+ int stackSize = backtrace(stackTrace, 128);
+ char** mangledSymbols = backtrace_symbols(stackTrace, stackSize);
+ wpi::SmallString<1024> buf;
+ wpi::raw_svector_ostream trace(buf);
+
+ for (int i = offset; i < stackSize; i++) {
+ // Only print recursive functions once in a row.
+ if (i == 0 || stackTrace[i] != stackTrace[i - 1]) {
+ trace << "\tat " << demangle(mangledSymbols[i]) << "\n";
+ }
+ }
+
+ std::free(mangledSymbols);
+
+ return trace.str();
+}
+
+#else
+static std::string demangle(char const* mangledSymbol) {
+ return "no demangling on windows";
+}
+
+std::string GetStackTrace(int offset) { return "no stack trace on windows"; }
+#endif
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/cpp/Victor.cpp b/wpilibc/src/main/native/cpp/Victor.cpp
new file mode 100644
index 0000000..2c29ece
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Victor.cpp
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/Victor.h"
+
+#include <hal/HAL.h>
+
+using namespace frc;
+
+Victor::Victor(int channel) : PWMSpeedController(channel) {
+ /* Note that the Victor uses the following bounds for PWM values. These
+ * values were determined empirically and optimized for the Victor 888. These
+ * values should work reasonably well for Victor 884 controllers as well but
+ * if users experience issues such as asymmetric behaviour around the deadband
+ * or inability to saturate the controller in either direction, calibration is
+ * recommended. The calibration procedure can be found in the Victor 884 User
+ * Manual available from IFI.
+ *
+ * 2.027ms = full "forward"
+ * 1.525ms = the "high end" of the deadband range
+ * 1.507ms = center of the deadband range (off)
+ * 1.49ms = the "low end" of the deadband range
+ * 1.026ms = full "reverse"
+ */
+ SetBounds(2.027, 1.525, 1.507, 1.49, 1.026);
+ SetPeriodMultiplier(kPeriodMultiplier_2X);
+ SetSpeed(0.0);
+ SetZeroLatch();
+
+ HAL_Report(HALUsageReporting::kResourceType_Victor, GetChannel());
+ SetName("Victor", GetChannel());
+}
diff --git a/wpilibc/src/main/native/cpp/VictorSP.cpp b/wpilibc/src/main/native/cpp/VictorSP.cpp
new file mode 100644
index 0000000..5e2b6b9
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/VictorSP.cpp
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/VictorSP.h"
+
+#include <hal/HAL.h>
+
+using namespace frc;
+
+VictorSP::VictorSP(int channel) : PWMSpeedController(channel) {
+ /* Note that the VictorSP uses the following bounds for PWM values. These
+ * values should work reasonably well for most controllers, but if users
+ * experience issues such as asymmetric behavior around the deadband or
+ * inability to saturate the controller in either direction, calibration is
+ * recommended. The calibration procedure can be found in the VictorSP User
+ * Manual available from Vex.
+ *
+ * 2.004ms = full "forward"
+ * 1.52ms = the "high end" of the deadband range
+ * 1.50ms = center of the deadband range (off)
+ * 1.48ms = the "low end" of the deadband range
+ * 0.997ms = full "reverse"
+ */
+ SetBounds(2.004, 1.52, 1.50, 1.48, .997);
+ SetPeriodMultiplier(kPeriodMultiplier_1X);
+ SetSpeed(0.0);
+ SetZeroLatch();
+
+ HAL_Report(HALUsageReporting::kResourceType_VictorSP, GetChannel());
+ SetName("VictorSP", GetChannel());
+}
diff --git a/wpilibc/src/main/native/cpp/Watchdog.cpp b/wpilibc/src/main/native/cpp/Watchdog.cpp
new file mode 100644
index 0000000..b67f94d
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/Watchdog.cpp
@@ -0,0 +1,184 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/Watchdog.h"
+
+#include <wpi/Format.h>
+#include <wpi/PriorityQueue.h>
+#include <wpi/raw_ostream.h>
+
+using namespace frc;
+
+constexpr std::chrono::milliseconds Watchdog::kMinPrintPeriod;
+
+class Watchdog::Thread : public wpi::SafeThread {
+ public:
+ template <typename T>
+ struct DerefGreater : public std::binary_function<T, T, bool> {
+ constexpr bool operator()(const T& lhs, const T& rhs) const {
+ return *lhs > *rhs;
+ }
+ };
+
+ wpi::PriorityQueue<Watchdog*, std::vector<Watchdog*>, DerefGreater<Watchdog*>>
+ m_watchdogs;
+
+ private:
+ void Main() override;
+};
+
+void Watchdog::Thread::Main() {
+ std::unique_lock<wpi::mutex> lock(m_mutex);
+
+ while (m_active) {
+ if (m_watchdogs.size() > 0) {
+ if (m_cond.wait_until(lock, m_watchdogs.top()->m_expirationTime) ==
+ std::cv_status::timeout) {
+ if (m_watchdogs.size() == 0 ||
+ m_watchdogs.top()->m_expirationTime > hal::fpga_clock::now()) {
+ continue;
+ }
+
+ // If the condition variable timed out, that means a Watchdog timeout
+ // has occurred, so call its timeout function.
+ auto watchdog = m_watchdogs.top();
+ m_watchdogs.pop();
+
+ auto now = hal::fpga_clock::now();
+ if (now - watchdog->m_lastTimeoutPrintTime > kMinPrintPeriod) {
+ watchdog->m_lastTimeoutPrintTime = now;
+ if (!watchdog->m_suppressTimeoutMessage) {
+ wpi::outs() << "Watchdog not fed within "
+ << wpi::format("%.6f",
+ watchdog->m_timeout.count() / 1.0e6)
+ << "s\n";
+ }
+ }
+
+ // Set expiration flag before calling the callback so any manipulation
+ // of the flag in the callback (e.g., calling Disable()) isn't
+ // clobbered.
+ watchdog->m_isExpired = true;
+
+ lock.unlock();
+ watchdog->m_callback();
+ lock.lock();
+ }
+ // Otherwise, a Watchdog removed itself from the queue (it notifies the
+ // scheduler of this) or a spurious wakeup occurred, so just rewait with
+ // the soonest watchdog timeout.
+ } else {
+ m_cond.wait(lock, [&] { return m_watchdogs.size() > 0 || !m_active; });
+ }
+ }
+}
+
+Watchdog::Watchdog(double timeout, std::function<void()> callback)
+ : m_timeout(static_cast<int64_t>(timeout * 1.0e6)),
+ m_callback(callback),
+ m_owner(&GetThreadOwner()) {}
+
+Watchdog::~Watchdog() { Disable(); }
+
+double Watchdog::GetTime() const {
+ return (hal::fpga_clock::now() - m_startTime).count() / 1.0e6;
+}
+
+void Watchdog::SetTimeout(double timeout) {
+ m_startTime = hal::fpga_clock::now();
+ m_epochs.clear();
+
+ // Locks mutex
+ auto thr = m_owner->GetThread();
+ if (!thr) return;
+
+ m_timeout = std::chrono::microseconds(static_cast<int64_t>(timeout * 1.0e6));
+ m_isExpired = false;
+
+ thr->m_watchdogs.remove(this);
+ m_expirationTime = m_startTime + m_timeout;
+ thr->m_watchdogs.emplace(this);
+ thr->m_cond.notify_all();
+}
+
+double Watchdog::GetTimeout() const {
+ // Locks mutex
+ auto thr = m_owner->GetThread();
+
+ return m_timeout.count() / 1.0e6;
+}
+
+bool Watchdog::IsExpired() const {
+ // Locks mutex
+ auto thr = m_owner->GetThread();
+
+ return m_isExpired;
+}
+
+void Watchdog::AddEpoch(wpi::StringRef epochName) {
+ auto currentTime = hal::fpga_clock::now();
+ m_epochs[epochName] = currentTime - m_startTime;
+ m_startTime = currentTime;
+}
+
+void Watchdog::PrintEpochs() {
+ auto now = hal::fpga_clock::now();
+ if (now - m_lastEpochsPrintTime > kMinPrintPeriod) {
+ m_lastEpochsPrintTime = now;
+ for (const auto& epoch : m_epochs) {
+ wpi::outs() << '\t' << epoch.getKey() << ": "
+ << wpi::format("%.6f", epoch.getValue().count() / 1.0e6)
+ << "s\n";
+ }
+ }
+}
+
+void Watchdog::Reset() { Enable(); }
+
+void Watchdog::Enable() {
+ m_startTime = hal::fpga_clock::now();
+ m_epochs.clear();
+
+ // Locks mutex
+ auto thr = m_owner->GetThread();
+ if (!thr) return;
+
+ m_isExpired = false;
+
+ thr->m_watchdogs.remove(this);
+ m_expirationTime = m_startTime + m_timeout;
+ thr->m_watchdogs.emplace(this);
+ thr->m_cond.notify_all();
+}
+
+void Watchdog::Disable() {
+ // Locks mutex
+ auto thr = m_owner->GetThread();
+ if (!thr) return;
+
+ m_isExpired = false;
+
+ thr->m_watchdogs.remove(this);
+ thr->m_cond.notify_all();
+}
+
+void Watchdog::SuppressTimeoutMessage(bool suppress) {
+ m_suppressTimeoutMessage = suppress;
+}
+
+bool Watchdog::operator>(const Watchdog& rhs) {
+ return m_expirationTime > rhs.m_expirationTime;
+}
+
+wpi::SafeThreadOwner<Watchdog::Thread>& Watchdog::GetThreadOwner() {
+ static wpi::SafeThreadOwner<Thread> inst = [] {
+ wpi::SafeThreadOwner<Watchdog::Thread> inst;
+ inst.Start();
+ return inst;
+ }();
+ return inst;
+}
diff --git a/wpilibc/src/main/native/cpp/XboxController.cpp b/wpilibc/src/main/native/cpp/XboxController.cpp
new file mode 100644
index 0000000..fa54980
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/XboxController.cpp
@@ -0,0 +1,160 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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 "frc/XboxController.h"
+
+#include <hal/HAL.h>
+
+using namespace frc;
+
+XboxController::XboxController(int port) : GenericHID(port) {
+ HAL_Report(HALUsageReporting::kResourceType_XboxController, port);
+}
+
+double XboxController::GetX(JoystickHand hand) const {
+ if (hand == kLeftHand) {
+ return GetRawAxis(0);
+ } else {
+ return GetRawAxis(4);
+ }
+}
+
+double XboxController::GetY(JoystickHand hand) const {
+ if (hand == kLeftHand) {
+ return GetRawAxis(1);
+ } else {
+ return GetRawAxis(5);
+ }
+}
+
+double XboxController::GetTriggerAxis(JoystickHand hand) const {
+ if (hand == kLeftHand) {
+ return GetRawAxis(2);
+ } else {
+ return GetRawAxis(3);
+ }
+}
+
+bool XboxController::GetBumper(JoystickHand hand) const {
+ if (hand == kLeftHand) {
+ return GetRawButton(static_cast<int>(Button::kBumperLeft));
+ } else {
+ return GetRawButton(static_cast<int>(Button::kBumperRight));
+ }
+}
+
+bool XboxController::GetBumperPressed(JoystickHand hand) {
+ if (hand == kLeftHand) {
+ return GetRawButtonPressed(static_cast<int>(Button::kBumperLeft));
+ } else {
+ return GetRawButtonPressed(static_cast<int>(Button::kBumperRight));
+ }
+}
+
+bool XboxController::GetBumperReleased(JoystickHand hand) {
+ if (hand == kLeftHand) {
+ return GetRawButtonReleased(static_cast<int>(Button::kBumperLeft));
+ } else {
+ return GetRawButtonReleased(static_cast<int>(Button::kBumperRight));
+ }
+}
+
+bool XboxController::GetStickButton(JoystickHand hand) const {
+ if (hand == kLeftHand) {
+ return GetRawButton(static_cast<int>(Button::kStickLeft));
+ } else {
+ return GetRawButton(static_cast<int>(Button::kStickRight));
+ }
+}
+
+bool XboxController::GetStickButtonPressed(JoystickHand hand) {
+ if (hand == kLeftHand) {
+ return GetRawButtonPressed(static_cast<int>(Button::kStickLeft));
+ } else {
+ return GetRawButtonPressed(static_cast<int>(Button::kStickRight));
+ }
+}
+
+bool XboxController::GetStickButtonReleased(JoystickHand hand) {
+ if (hand == kLeftHand) {
+ return GetRawButtonReleased(static_cast<int>(Button::kStickLeft));
+ } else {
+ return GetRawButtonReleased(static_cast<int>(Button::kStickRight));
+ }
+}
+
+bool XboxController::GetAButton() const {
+ return GetRawButton(static_cast<int>(Button::kA));
+}
+
+bool XboxController::GetAButtonPressed() {
+ return GetRawButtonPressed(static_cast<int>(Button::kA));
+}
+
+bool XboxController::GetAButtonReleased() {
+ return GetRawButtonReleased(static_cast<int>(Button::kA));
+}
+
+bool XboxController::GetBButton() const {
+ return GetRawButton(static_cast<int>(Button::kB));
+}
+
+bool XboxController::GetBButtonPressed() {
+ return GetRawButtonPressed(static_cast<int>(Button::kB));
+}
+
+bool XboxController::GetBButtonReleased() {
+ return GetRawButtonReleased(static_cast<int>(Button::kB));
+}
+
+bool XboxController::GetXButton() const {
+ return GetRawButton(static_cast<int>(Button::kX));
+}
+
+bool XboxController::GetXButtonPressed() {
+ return GetRawButtonPressed(static_cast<int>(Button::kX));
+}
+
+bool XboxController::GetXButtonReleased() {
+ return GetRawButtonReleased(static_cast<int>(Button::kX));
+}
+
+bool XboxController::GetYButton() const {
+ return GetRawButton(static_cast<int>(Button::kY));
+}
+
+bool XboxController::GetYButtonPressed() {
+ return GetRawButtonPressed(static_cast<int>(Button::kY));
+}
+
+bool XboxController::GetYButtonReleased() {
+ return GetRawButtonReleased(static_cast<int>(Button::kY));
+}
+
+bool XboxController::GetBackButton() const {
+ return GetRawButton(static_cast<int>(Button::kBack));
+}
+
+bool XboxController::GetBackButtonPressed() {
+ return GetRawButtonPressed(static_cast<int>(Button::kBack));
+}
+
+bool XboxController::GetBackButtonReleased() {
+ return GetRawButtonReleased(static_cast<int>(Button::kBack));
+}
+
+bool XboxController::GetStartButton() const {
+ return GetRawButton(static_cast<int>(Button::kStart));
+}
+
+bool XboxController::GetStartButtonPressed() {
+ return GetRawButtonPressed(static_cast<int>(Button::kStart));
+}
+
+bool XboxController::GetStartButtonReleased() {
+ return GetRawButtonReleased(static_cast<int>(Button::kStart));
+}
diff --git a/wpilibc/src/main/native/cpp/buttons/Button.cpp b/wpilibc/src/main/native/cpp/buttons/Button.cpp
new file mode 100644
index 0000000..45ede65
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/buttons/Button.cpp
@@ -0,0 +1,20 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/buttons/Button.h"
+
+using namespace frc;
+
+void Button::WhenPressed(Command* command) { WhenActive(command); }
+
+void Button::WhileHeld(Command* command) { WhileActive(command); }
+
+void Button::WhenReleased(Command* command) { WhenInactive(command); }
+
+void Button::CancelWhenPressed(Command* command) { CancelWhenActive(command); }
+
+void Button::ToggleWhenPressed(Command* command) { ToggleWhenActive(command); }
diff --git a/wpilibc/src/main/native/cpp/buttons/ButtonScheduler.cpp b/wpilibc/src/main/native/cpp/buttons/ButtonScheduler.cpp
new file mode 100644
index 0000000..1e10255
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/buttons/ButtonScheduler.cpp
@@ -0,0 +1,17 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/buttons/ButtonScheduler.h"
+
+#include "frc/commands/Scheduler.h"
+
+using namespace frc;
+
+ButtonScheduler::ButtonScheduler(bool last, Trigger* button, Command* orders)
+ : m_pressedLast(last), m_button(button), m_command(orders) {}
+
+void ButtonScheduler::Start() { Scheduler::GetInstance()->AddButton(this); }
diff --git a/wpilibc/src/main/native/cpp/buttons/CancelButtonScheduler.cpp b/wpilibc/src/main/native/cpp/buttons/CancelButtonScheduler.cpp
new file mode 100644
index 0000000..39d1d25
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/buttons/CancelButtonScheduler.cpp
@@ -0,0 +1,27 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/buttons/CancelButtonScheduler.h"
+
+#include "frc/buttons/Button.h"
+#include "frc/commands/Command.h"
+
+using namespace frc;
+
+CancelButtonScheduler::CancelButtonScheduler(bool last, Trigger* button,
+ Command* orders)
+ : ButtonScheduler(last, button, orders) {}
+
+void CancelButtonScheduler::Execute() {
+ bool pressed = m_button->Grab();
+
+ if (!m_pressedLast && pressed) {
+ m_command->Cancel();
+ }
+
+ m_pressedLast = pressed;
+}
diff --git a/wpilibc/src/main/native/cpp/buttons/HeldButtonScheduler.cpp b/wpilibc/src/main/native/cpp/buttons/HeldButtonScheduler.cpp
new file mode 100644
index 0000000..feaa3c6
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/buttons/HeldButtonScheduler.cpp
@@ -0,0 +1,29 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/buttons/HeldButtonScheduler.h"
+
+#include "frc/buttons/Button.h"
+#include "frc/commands/Command.h"
+
+using namespace frc;
+
+HeldButtonScheduler::HeldButtonScheduler(bool last, Trigger* button,
+ Command* orders)
+ : ButtonScheduler(last, button, orders) {}
+
+void HeldButtonScheduler::Execute() {
+ bool pressed = m_button->Grab();
+
+ if (pressed) {
+ m_command->Start();
+ } else if (m_pressedLast && !pressed) {
+ m_command->Cancel();
+ }
+
+ m_pressedLast = pressed;
+}
diff --git a/wpilibc/src/main/native/cpp/buttons/InternalButton.cpp b/wpilibc/src/main/native/cpp/buttons/InternalButton.cpp
new file mode 100644
index 0000000..cac67c4
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/buttons/InternalButton.cpp
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/buttons/InternalButton.h"
+
+using namespace frc;
+
+InternalButton::InternalButton(bool inverted)
+ : m_pressed(inverted), m_inverted(inverted) {}
+
+void InternalButton::SetInverted(bool inverted) { m_inverted = inverted; }
+
+void InternalButton::SetPressed(bool pressed) { m_pressed = pressed; }
+
+bool InternalButton::Get() { return m_pressed ^ m_inverted; }
diff --git a/wpilibc/src/main/native/cpp/buttons/JoystickButton.cpp b/wpilibc/src/main/native/cpp/buttons/JoystickButton.cpp
new file mode 100644
index 0000000..2c93be2
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/buttons/JoystickButton.cpp
@@ -0,0 +1,15 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/buttons/JoystickButton.h"
+
+using namespace frc;
+
+JoystickButton::JoystickButton(GenericHID* joystick, int buttonNumber)
+ : m_joystick(joystick), m_buttonNumber(buttonNumber) {}
+
+bool JoystickButton::Get() { return m_joystick->GetRawButton(m_buttonNumber); }
diff --git a/wpilibc/src/main/native/cpp/buttons/NetworkButton.cpp b/wpilibc/src/main/native/cpp/buttons/NetworkButton.cpp
new file mode 100644
index 0000000..5e8b1e0
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/buttons/NetworkButton.cpp
@@ -0,0 +1,26 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/buttons/NetworkButton.h"
+
+#include <networktables/NetworkTable.h>
+#include <networktables/NetworkTableInstance.h>
+
+using namespace frc;
+
+NetworkButton::NetworkButton(const wpi::Twine& tableName,
+ const wpi::Twine& field)
+ : NetworkButton(nt::NetworkTableInstance::GetDefault().GetTable(tableName),
+ field) {}
+
+NetworkButton::NetworkButton(std::shared_ptr<nt::NetworkTable> table,
+ const wpi::Twine& field)
+ : m_entry(table->GetEntry(field)) {}
+
+bool NetworkButton::Get() {
+ return m_entry.GetInstance().IsConnected() && m_entry.GetBoolean(false);
+}
diff --git a/wpilibc/src/main/native/cpp/buttons/POVButton.cpp b/wpilibc/src/main/native/cpp/buttons/POVButton.cpp
new file mode 100644
index 0000000..6729923
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/buttons/POVButton.cpp
@@ -0,0 +1,15 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/buttons/POVButton.h"
+
+using namespace frc;
+
+POVButton::POVButton(GenericHID& joystick, int angle, int povNumber)
+ : m_joystick(&joystick), m_angle(angle), m_povNumber(povNumber) {}
+
+bool POVButton::Get() { return m_joystick->GetPOV(m_povNumber) == m_angle; }
diff --git a/wpilibc/src/main/native/cpp/buttons/PressedButtonScheduler.cpp b/wpilibc/src/main/native/cpp/buttons/PressedButtonScheduler.cpp
new file mode 100644
index 0000000..a964117
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/buttons/PressedButtonScheduler.cpp
@@ -0,0 +1,27 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/buttons/PressedButtonScheduler.h"
+
+#include "frc/buttons/Button.h"
+#include "frc/commands/Command.h"
+
+using namespace frc;
+
+PressedButtonScheduler::PressedButtonScheduler(bool last, Trigger* button,
+ Command* orders)
+ : ButtonScheduler(last, button, orders) {}
+
+void PressedButtonScheduler::Execute() {
+ bool pressed = m_button->Grab();
+
+ if (!m_pressedLast && pressed) {
+ m_command->Start();
+ }
+
+ m_pressedLast = pressed;
+}
diff --git a/wpilibc/src/main/native/cpp/buttons/ReleasedButtonScheduler.cpp b/wpilibc/src/main/native/cpp/buttons/ReleasedButtonScheduler.cpp
new file mode 100644
index 0000000..6d67004
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/buttons/ReleasedButtonScheduler.cpp
@@ -0,0 +1,27 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/buttons/ReleasedButtonScheduler.h"
+
+#include "frc/buttons/Button.h"
+#include "frc/commands/Command.h"
+
+using namespace frc;
+
+ReleasedButtonScheduler::ReleasedButtonScheduler(bool last, Trigger* button,
+ Command* orders)
+ : ButtonScheduler(last, button, orders) {}
+
+void ReleasedButtonScheduler::Execute() {
+ bool pressed = m_button->Grab();
+
+ if (m_pressedLast && !pressed) {
+ m_command->Start();
+ }
+
+ m_pressedLast = pressed;
+}
diff --git a/wpilibc/src/main/native/cpp/buttons/ToggleButtonScheduler.cpp b/wpilibc/src/main/native/cpp/buttons/ToggleButtonScheduler.cpp
new file mode 100644
index 0000000..b722d45
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/buttons/ToggleButtonScheduler.cpp
@@ -0,0 +1,31 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/buttons/ToggleButtonScheduler.h"
+
+#include "frc/buttons/Button.h"
+#include "frc/commands/Command.h"
+
+using namespace frc;
+
+ToggleButtonScheduler::ToggleButtonScheduler(bool last, Trigger* button,
+ Command* orders)
+ : ButtonScheduler(last, button, orders) {}
+
+void ToggleButtonScheduler::Execute() {
+ bool pressed = m_button->Grab();
+
+ if (!m_pressedLast && pressed) {
+ if (m_command->IsRunning()) {
+ m_command->Cancel();
+ } else {
+ m_command->Start();
+ }
+ }
+
+ m_pressedLast = pressed;
+}
diff --git a/wpilibc/src/main/native/cpp/buttons/Trigger.cpp b/wpilibc/src/main/native/cpp/buttons/Trigger.cpp
new file mode 100644
index 0000000..2ccaaf2
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/buttons/Trigger.cpp
@@ -0,0 +1,50 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/buttons/Button.h"
+#include "frc/buttons/CancelButtonScheduler.h"
+#include "frc/buttons/HeldButtonScheduler.h"
+#include "frc/buttons/PressedButtonScheduler.h"
+#include "frc/buttons/ReleasedButtonScheduler.h"
+#include "frc/buttons/ToggleButtonScheduler.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+bool Trigger::Grab() { return Get() || m_sendablePressed; }
+
+void Trigger::WhenActive(Command* command) {
+ auto pbs = new PressedButtonScheduler(Grab(), this, command);
+ pbs->Start();
+}
+
+void Trigger::WhileActive(Command* command) {
+ auto hbs = new HeldButtonScheduler(Grab(), this, command);
+ hbs->Start();
+}
+
+void Trigger::WhenInactive(Command* command) {
+ auto rbs = new ReleasedButtonScheduler(Grab(), this, command);
+ rbs->Start();
+}
+
+void Trigger::CancelWhenActive(Command* command) {
+ auto cbs = new CancelButtonScheduler(Grab(), this, command);
+ cbs->Start();
+}
+
+void Trigger::ToggleWhenActive(Command* command) {
+ auto tbs = new ToggleButtonScheduler(Grab(), this, command);
+ tbs->Start();
+}
+
+void Trigger::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Button");
+ builder.SetSafeState([=]() { m_sendablePressed = false; });
+ builder.AddBooleanProperty("pressed", [=]() { return Grab(); },
+ [=](bool value) { m_sendablePressed = value; });
+}
diff --git a/wpilibc/src/main/native/cpp/commands/Command.cpp b/wpilibc/src/main/native/cpp/commands/Command.cpp
new file mode 100644
index 0000000..ad7824a
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/Command.cpp
@@ -0,0 +1,244 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/commands/Command.h"
+
+#include <typeinfo>
+
+#include "frc/RobotState.h"
+#include "frc/Timer.h"
+#include "frc/WPIErrors.h"
+#include "frc/commands/CommandGroup.h"
+#include "frc/commands/Scheduler.h"
+#include "frc/livewindow/LiveWindow.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+int Command::m_commandCounter = 0;
+
+Command::Command() : Command("", -1.0) {}
+
+Command::Command(const wpi::Twine& name) : Command(name, -1.0) {}
+
+Command::Command(double timeout) : Command("", timeout) {}
+
+Command::Command(Subsystem& subsystem) : Command("", -1.0) {
+ Requires(&subsystem);
+}
+
+Command::Command(const wpi::Twine& name, double timeout) : SendableBase(false) {
+ // We use -1.0 to indicate no timeout.
+ if (timeout < 0.0 && timeout != -1.0)
+ wpi_setWPIErrorWithContext(ParameterOutOfRange, "timeout < 0.0");
+
+ m_timeout = timeout;
+
+ // If name contains an empty string
+ if (name.isTriviallyEmpty() ||
+ (name.isSingleStringRef() && name.getSingleStringRef().empty())) {
+ SetName("Command_" + wpi::Twine(typeid(*this).name()));
+ } else {
+ SetName(name);
+ }
+}
+
+Command::Command(const wpi::Twine& name, Subsystem& subsystem)
+ : Command(name, -1.0) {
+ Requires(&subsystem);
+}
+
+Command::Command(double timeout, Subsystem& subsystem) : Command("", timeout) {
+ Requires(&subsystem);
+}
+
+Command::Command(const wpi::Twine& name, double timeout, Subsystem& subsystem)
+ : Command(name, timeout) {
+ Requires(&subsystem);
+}
+
+double Command::TimeSinceInitialized() const {
+ if (m_startTime < 0.0)
+ return 0.0;
+ else
+ return Timer::GetFPGATimestamp() - m_startTime;
+}
+
+void Command::Requires(Subsystem* subsystem) {
+ if (!AssertUnlocked("Can not add new requirement to command")) return;
+
+ if (subsystem != nullptr)
+ m_requirements.insert(subsystem);
+ else
+ wpi_setWPIErrorWithContext(NullParameter, "subsystem");
+}
+
+void Command::Start() {
+ LockChanges();
+ if (m_parent != nullptr)
+ wpi_setWPIErrorWithContext(
+ CommandIllegalUse,
+ "Can not start a command that is part of a command group");
+
+ m_completed = false;
+ Scheduler::GetInstance()->AddCommand(this);
+}
+
+bool Command::Run() {
+ if (!m_runWhenDisabled && m_parent == nullptr && RobotState::IsDisabled())
+ Cancel();
+
+ if (IsCanceled()) return false;
+
+ if (!m_initialized) {
+ m_initialized = true;
+ StartTiming();
+ _Initialize();
+ Initialize();
+ }
+ _Execute();
+ Execute();
+ return !IsFinished();
+}
+
+void Command::Cancel() {
+ if (m_parent != nullptr)
+ wpi_setWPIErrorWithContext(
+ CommandIllegalUse,
+ "Can not cancel a command that is part of a command group");
+
+ _Cancel();
+}
+
+bool Command::IsRunning() const { return m_running; }
+
+bool Command::IsInitialized() const { return m_initialized; }
+
+bool Command::IsCompleted() const { return m_completed; }
+
+bool Command::IsCanceled() const { return m_canceled; }
+
+bool Command::IsInterruptible() const { return m_interruptible; }
+
+void Command::SetInterruptible(bool interruptible) {
+ m_interruptible = interruptible;
+}
+
+bool Command::DoesRequire(Subsystem* system) const {
+ return m_requirements.count(system) > 0;
+}
+
+const Command::SubsystemSet& Command::GetRequirements() const {
+ return m_requirements;
+}
+
+CommandGroup* Command::GetGroup() const { return m_parent; }
+
+void Command::SetRunWhenDisabled(bool run) { m_runWhenDisabled = run; }
+
+bool Command::WillRunWhenDisabled() const { return m_runWhenDisabled; }
+
+int Command::GetID() const { return m_commandID; }
+
+void Command::SetTimeout(double timeout) {
+ if (timeout < 0.0)
+ wpi_setWPIErrorWithContext(ParameterOutOfRange, "timeout < 0.0");
+ else
+ m_timeout = timeout;
+}
+
+bool Command::IsTimedOut() const {
+ return m_timeout != -1 && TimeSinceInitialized() >= m_timeout;
+}
+
+bool Command::AssertUnlocked(const std::string& message) {
+ if (m_locked) {
+ std::string buf =
+ message + " after being started or being added to a command group";
+ wpi_setWPIErrorWithContext(CommandIllegalUse, buf);
+ return false;
+ }
+ return true;
+}
+
+void Command::SetParent(CommandGroup* parent) {
+ if (parent == nullptr) {
+ wpi_setWPIErrorWithContext(NullParameter, "parent");
+ } else if (m_parent != nullptr) {
+ wpi_setWPIErrorWithContext(CommandIllegalUse,
+ "Can not give command to a command group after "
+ "already being put in a command group");
+ } else {
+ LockChanges();
+ m_parent = parent;
+ }
+}
+
+bool Command::IsParented() const { return m_parent != nullptr; }
+
+void Command::ClearRequirements() { m_requirements.clear(); }
+
+void Command::Initialize() {}
+
+void Command::Execute() {}
+
+void Command::End() {}
+
+void Command::Interrupted() { End(); }
+
+void Command::_Initialize() { m_completed = false; }
+
+void Command::_Interrupted() { m_completed = true; }
+
+void Command::_Execute() {}
+
+void Command::_End() { m_completed = true; }
+
+void Command::_Cancel() {
+ if (IsRunning()) m_canceled = true;
+}
+
+void Command::LockChanges() { m_locked = true; }
+
+void Command::Removed() {
+ if (m_initialized) {
+ if (IsCanceled()) {
+ Interrupted();
+ _Interrupted();
+ } else {
+ End();
+ _End();
+ }
+ }
+ m_initialized = false;
+ m_canceled = false;
+ m_running = false;
+ m_completed = true;
+}
+
+void Command::StartRunning() {
+ m_running = true;
+ m_startTime = -1;
+ m_completed = false;
+}
+
+void Command::StartTiming() { m_startTime = Timer::GetFPGATimestamp(); }
+
+void Command::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Command");
+ builder.AddStringProperty(".name", [=]() { return GetName(); }, nullptr);
+ builder.AddBooleanProperty("running", [=]() { return IsRunning(); },
+ [=](bool value) {
+ if (value) {
+ if (!IsRunning()) Start();
+ } else {
+ if (IsRunning()) Cancel();
+ }
+ });
+ builder.AddBooleanProperty(".isParented", [=]() { return IsParented(); },
+ nullptr);
+}
diff --git a/wpilibc/src/main/native/cpp/commands/CommandGroup.cpp b/wpilibc/src/main/native/cpp/commands/CommandGroup.cpp
new file mode 100644
index 0000000..eac1746
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/CommandGroup.cpp
@@ -0,0 +1,243 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/commands/CommandGroup.h"
+
+#include "frc/WPIErrors.h"
+
+using namespace frc;
+
+CommandGroup::CommandGroup(const wpi::Twine& name) : Command(name) {}
+
+void CommandGroup::AddSequential(Command* command) {
+ if (command == nullptr) {
+ wpi_setWPIErrorWithContext(NullParameter, "command");
+ return;
+ }
+ if (!AssertUnlocked("Cannot add new command to command group")) return;
+
+ m_commands.emplace_back(command, CommandGroupEntry::kSequence_InSequence);
+
+ command->SetParent(this);
+
+ // Iterate through command->GetRequirements() and call Requires() on each
+ // required subsystem
+ for (auto&& requirement : command->GetRequirements()) Requires(requirement);
+}
+
+void CommandGroup::AddSequential(Command* command, double timeout) {
+ if (command == nullptr) {
+ wpi_setWPIErrorWithContext(NullParameter, "command");
+ return;
+ }
+ if (!AssertUnlocked("Cannot add new command to command group")) return;
+ if (timeout < 0.0) {
+ wpi_setWPIErrorWithContext(ParameterOutOfRange, "timeout < 0.0");
+ return;
+ }
+
+ m_commands.emplace_back(command, CommandGroupEntry::kSequence_InSequence,
+ timeout);
+
+ command->SetParent(this);
+
+ // Iterate through command->GetRequirements() and call Requires() on each
+ // required subsystem
+ for (auto&& requirement : command->GetRequirements()) Requires(requirement);
+}
+
+void CommandGroup::AddParallel(Command* command) {
+ if (command == nullptr) {
+ wpi_setWPIErrorWithContext(NullParameter, "command");
+ return;
+ }
+ if (!AssertUnlocked("Cannot add new command to command group")) return;
+
+ m_commands.emplace_back(command, CommandGroupEntry::kSequence_BranchChild);
+
+ command->SetParent(this);
+
+ // Iterate through command->GetRequirements() and call Requires() on each
+ // required subsystem
+ for (auto&& requirement : command->GetRequirements()) Requires(requirement);
+}
+
+void CommandGroup::AddParallel(Command* command, double timeout) {
+ if (command == nullptr) {
+ wpi_setWPIErrorWithContext(NullParameter, "command");
+ return;
+ }
+ if (!AssertUnlocked("Cannot add new command to command group")) return;
+ if (timeout < 0.0) {
+ wpi_setWPIErrorWithContext(ParameterOutOfRange, "timeout < 0.0");
+ return;
+ }
+
+ m_commands.emplace_back(command, CommandGroupEntry::kSequence_BranchChild,
+ timeout);
+
+ command->SetParent(this);
+
+ // Iterate through command->GetRequirements() and call Requires() on each
+ // required subsystem
+ for (auto&& requirement : command->GetRequirements()) Requires(requirement);
+}
+
+bool CommandGroup::IsInterruptible() const {
+ if (!Command::IsInterruptible()) return false;
+
+ if (m_currentCommandIndex != -1 &&
+ static_cast<size_t>(m_currentCommandIndex) < m_commands.size()) {
+ Command* cmd = m_commands[m_currentCommandIndex].m_command;
+ if (!cmd->IsInterruptible()) return false;
+ }
+
+ for (const auto& child : m_children) {
+ if (!child->m_command->IsInterruptible()) return false;
+ }
+
+ return true;
+}
+
+int CommandGroup::GetSize() const { return m_children.size(); }
+
+void CommandGroup::Initialize() {}
+
+void CommandGroup::Execute() {}
+
+bool CommandGroup::IsFinished() {
+ return static_cast<size_t>(m_currentCommandIndex) >= m_commands.size() &&
+ m_children.empty();
+}
+
+void CommandGroup::End() {}
+
+void CommandGroup::Interrupted() {}
+
+void CommandGroup::_Initialize() { m_currentCommandIndex = -1; }
+
+void CommandGroup::_Execute() {
+ CommandGroupEntry* entry;
+ Command* cmd = nullptr;
+ bool firstRun = false;
+
+ if (m_currentCommandIndex == -1) {
+ firstRun = true;
+ m_currentCommandIndex = 0;
+ }
+
+ // While there are still commands in this group to run
+ while (static_cast<size_t>(m_currentCommandIndex) < m_commands.size()) {
+ // If a command is prepared to run
+ if (cmd != nullptr) {
+ // If command timed out, cancel it so it's removed from the Scheduler
+ if (entry->IsTimedOut()) cmd->_Cancel();
+
+ // If command finished or was cancelled, remove it from Scheduler
+ if (cmd->Run()) {
+ break;
+ } else {
+ cmd->Removed();
+
+ // Advance to next command in group
+ m_currentCommandIndex++;
+ firstRun = true;
+ cmd = nullptr;
+ continue;
+ }
+ }
+
+ entry = &m_commands[m_currentCommandIndex];
+ cmd = nullptr;
+
+ switch (entry->m_state) {
+ case CommandGroupEntry::kSequence_InSequence:
+ cmd = entry->m_command;
+ if (firstRun) {
+ cmd->StartRunning();
+ CancelConflicts(cmd);
+ firstRun = false;
+ }
+ break;
+
+ case CommandGroupEntry::kSequence_BranchPeer:
+ // Start executing a parallel command and advance to next entry in group
+ m_currentCommandIndex++;
+ entry->m_command->Start();
+ break;
+
+ case CommandGroupEntry::kSequence_BranchChild:
+ m_currentCommandIndex++;
+
+ /* Causes scheduler to skip children of current command which require
+ * the same subsystems as it
+ */
+ CancelConflicts(entry->m_command);
+ entry->m_command->StartRunning();
+
+ // Add current command entry to list of children of this group
+ m_children.push_back(entry);
+ break;
+ }
+ }
+
+ // Run Children
+ for (auto& entry : m_children) {
+ auto child = entry->m_command;
+ if (entry->IsTimedOut()) {
+ child->_Cancel();
+ }
+
+ // If child finished or was cancelled, set it to nullptr. nullptr entries
+ // are removed later.
+ if (!child->Run()) {
+ child->Removed();
+ entry = nullptr;
+ }
+ }
+
+ m_children.erase(std::remove(m_children.begin(), m_children.end(), nullptr),
+ m_children.end());
+}
+
+void CommandGroup::_End() {
+ // Theoretically, we don't have to check this, but we do if teams override the
+ // IsFinished method
+ if (m_currentCommandIndex != -1 &&
+ static_cast<size_t>(m_currentCommandIndex) < m_commands.size()) {
+ Command* cmd = m_commands[m_currentCommandIndex].m_command;
+ cmd->_Cancel();
+ cmd->Removed();
+ }
+
+ for (auto& child : m_children) {
+ Command* cmd = child->m_command;
+ cmd->_Cancel();
+ cmd->Removed();
+ }
+ m_children.clear();
+}
+
+void CommandGroup::_Interrupted() { _End(); }
+
+void CommandGroup::CancelConflicts(Command* command) {
+ for (auto childIter = m_children.begin(); childIter != m_children.end();) {
+ Command* child = (*childIter)->m_command;
+ bool erased = false;
+
+ for (auto&& requirement : command->GetRequirements()) {
+ if (child->DoesRequire(requirement)) {
+ child->_Cancel();
+ child->Removed();
+ childIter = m_children.erase(childIter);
+ erased = true;
+ break;
+ }
+ }
+ if (!erased) childIter++;
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/commands/CommandGroupEntry.cpp b/wpilibc/src/main/native/cpp/commands/CommandGroupEntry.cpp
new file mode 100644
index 0000000..7a75f00
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/CommandGroupEntry.cpp
@@ -0,0 +1,23 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/commands/CommandGroupEntry.h"
+
+#include "frc/commands/Command.h"
+
+using namespace frc;
+
+CommandGroupEntry::CommandGroupEntry(Command* command, Sequence state,
+ double timeout)
+ : m_timeout(timeout), m_command(command), m_state(state) {}
+
+bool CommandGroupEntry::IsTimedOut() const {
+ if (m_timeout < 0.0) return false;
+ double time = m_command->TimeSinceInitialized();
+ if (time == 0.0) return false;
+ return time >= m_timeout;
+}
diff --git a/wpilibc/src/main/native/cpp/commands/ConditionalCommand.cpp b/wpilibc/src/main/native/cpp/commands/ConditionalCommand.cpp
new file mode 100644
index 0000000..c44f7ba
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/ConditionalCommand.cpp
@@ -0,0 +1,80 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/commands/ConditionalCommand.h"
+
+#include "frc/commands/Scheduler.h"
+
+using namespace frc;
+
+static void RequireAll(Command& command, Command* onTrue, Command* onFalse) {
+ if (onTrue != nullptr) {
+ for (auto requirement : onTrue->GetRequirements())
+ command.Requires(requirement);
+ }
+ if (onFalse != nullptr) {
+ for (auto requirement : onFalse->GetRequirements())
+ command.Requires(requirement);
+ }
+}
+
+ConditionalCommand::ConditionalCommand(Command* onTrue, Command* onFalse) {
+ m_onTrue = onTrue;
+ m_onFalse = onFalse;
+
+ RequireAll(*this, onTrue, onFalse);
+}
+
+ConditionalCommand::ConditionalCommand(const wpi::Twine& name, Command* onTrue,
+ Command* onFalse)
+ : Command(name) {
+ m_onTrue = onTrue;
+ m_onFalse = onFalse;
+
+ RequireAll(*this, onTrue, onFalse);
+}
+
+void ConditionalCommand::_Initialize() {
+ if (Condition()) {
+ m_chosenCommand = m_onTrue;
+ } else {
+ m_chosenCommand = m_onFalse;
+ }
+
+ if (m_chosenCommand != nullptr) {
+ // This is a hack to make cancelling the chosen command inside a
+ // CommandGroup work properly
+ m_chosenCommand->ClearRequirements();
+
+ m_chosenCommand->Start();
+ }
+ Command::_Initialize();
+}
+
+void ConditionalCommand::_Cancel() {
+ if (m_chosenCommand != nullptr && m_chosenCommand->IsRunning()) {
+ m_chosenCommand->Cancel();
+ }
+
+ Command::_Cancel();
+}
+
+bool ConditionalCommand::IsFinished() {
+ if (m_chosenCommand != nullptr) {
+ return m_chosenCommand->IsCompleted();
+ } else {
+ return true;
+ }
+}
+
+void ConditionalCommand::_Interrupted() {
+ if (m_chosenCommand != nullptr && m_chosenCommand->IsRunning()) {
+ m_chosenCommand->Cancel();
+ }
+
+ Command::_Interrupted();
+}
diff --git a/wpilibc/src/main/native/cpp/commands/InstantCommand.cpp b/wpilibc/src/main/native/cpp/commands/InstantCommand.cpp
new file mode 100644
index 0000000..88ebfde
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/InstantCommand.cpp
@@ -0,0 +1,45 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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 "frc/commands/InstantCommand.h"
+
+using namespace frc;
+
+InstantCommand::InstantCommand(const wpi::Twine& name) : Command(name) {}
+
+InstantCommand::InstantCommand(Subsystem& subsystem) : Command(subsystem) {}
+
+InstantCommand::InstantCommand(const wpi::Twine& name, Subsystem& subsystem)
+ : Command(name, subsystem) {}
+
+InstantCommand::InstantCommand(std::function<void()> func) : m_func(func) {}
+
+InstantCommand::InstantCommand(Subsystem& subsystem, std::function<void()> func)
+ : InstantCommand(subsystem) {
+ m_func = func;
+}
+
+InstantCommand::InstantCommand(const wpi::Twine& name,
+ std::function<void()> func)
+ : InstantCommand(name) {
+ m_func = func;
+}
+
+InstantCommand::InstantCommand(const wpi::Twine& name, Subsystem& subsystem,
+ std::function<void()> func)
+ : InstantCommand(name, subsystem) {
+ m_func = func;
+}
+
+void InstantCommand::_Initialize() {
+ Command::_Initialize();
+ if (m_func) {
+ m_func();
+ }
+}
+
+bool InstantCommand::IsFinished() { return true; }
diff --git a/wpilibc/src/main/native/cpp/commands/PIDCommand.cpp b/wpilibc/src/main/native/cpp/commands/PIDCommand.cpp
new file mode 100644
index 0000000..875d8fe
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/PIDCommand.cpp
@@ -0,0 +1,108 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/commands/PIDCommand.h"
+
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+PIDCommand::PIDCommand(const wpi::Twine& name, double p, double i, double d,
+ double f, double period)
+ : Command(name) {
+ m_controller = std::make_shared<PIDController>(p, i, d, this, this, period);
+}
+
+PIDCommand::PIDCommand(double p, double i, double d, double f, double period) {
+ m_controller =
+ std::make_shared<PIDController>(p, i, d, f, this, this, period);
+}
+
+PIDCommand::PIDCommand(const wpi::Twine& name, double p, double i, double d)
+ : Command(name) {
+ m_controller = std::make_shared<PIDController>(p, i, d, this, this);
+}
+
+PIDCommand::PIDCommand(const wpi::Twine& name, double p, double i, double d,
+ double period)
+ : Command(name) {
+ m_controller = std::make_shared<PIDController>(p, i, d, this, this, period);
+}
+
+PIDCommand::PIDCommand(double p, double i, double d) {
+ m_controller = std::make_shared<PIDController>(p, i, d, this, this);
+}
+
+PIDCommand::PIDCommand(double p, double i, double d, double period) {
+ m_controller = std::make_shared<PIDController>(p, i, d, this, this, period);
+}
+
+PIDCommand::PIDCommand(const wpi::Twine& name, double p, double i, double d,
+ double f, double period, Subsystem& subsystem)
+ : Command(name, subsystem) {
+ m_controller = std::make_shared<PIDController>(p, i, d, this, this, period);
+}
+
+PIDCommand::PIDCommand(double p, double i, double d, double f, double period,
+ Subsystem& subsystem)
+ : Command(subsystem) {
+ m_controller =
+ std::make_shared<PIDController>(p, i, d, f, this, this, period);
+}
+
+PIDCommand::PIDCommand(const wpi::Twine& name, double p, double i, double d,
+ Subsystem& subsystem)
+ : Command(name, subsystem) {
+ m_controller = std::make_shared<PIDController>(p, i, d, this, this);
+}
+
+PIDCommand::PIDCommand(const wpi::Twine& name, double p, double i, double d,
+ double period, Subsystem& subsystem)
+ : Command(name, subsystem) {
+ m_controller = std::make_shared<PIDController>(p, i, d, this, this, period);
+}
+
+PIDCommand::PIDCommand(double p, double i, double d, Subsystem& subsystem) {
+ m_controller = std::make_shared<PIDController>(p, i, d, this, this);
+}
+
+PIDCommand::PIDCommand(double p, double i, double d, double period,
+ Subsystem& subsystem) {
+ m_controller = std::make_shared<PIDController>(p, i, d, this, this, period);
+}
+
+void PIDCommand::_Initialize() { m_controller->Enable(); }
+
+void PIDCommand::_End() { m_controller->Disable(); }
+
+void PIDCommand::_Interrupted() { _End(); }
+
+void PIDCommand::SetSetpointRelative(double deltaSetpoint) {
+ SetSetpoint(GetSetpoint() + deltaSetpoint);
+}
+
+void PIDCommand::PIDWrite(double output) { UsePIDOutput(output); }
+
+double PIDCommand::PIDGet() { return ReturnPIDInput(); }
+
+std::shared_ptr<PIDController> PIDCommand::GetPIDController() const {
+ return m_controller;
+}
+
+void PIDCommand::SetSetpoint(double setpoint) {
+ m_controller->SetSetpoint(setpoint);
+}
+
+double PIDCommand::GetSetpoint() const { return m_controller->GetSetpoint(); }
+
+double PIDCommand::GetPosition() { return ReturnPIDInput(); }
+
+void PIDCommand::InitSendable(SendableBuilder& builder) {
+ m_controller->InitSendable(builder);
+ Command::InitSendable(builder);
+ builder.SetSmartDashboardType("PIDCommand");
+}
diff --git a/wpilibc/src/main/native/cpp/commands/PIDSubsystem.cpp b/wpilibc/src/main/native/cpp/commands/PIDSubsystem.cpp
new file mode 100644
index 0000000..0893da3
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/PIDSubsystem.cpp
@@ -0,0 +1,97 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/commands/PIDSubsystem.h"
+
+#include "frc/PIDController.h"
+
+using namespace frc;
+
+PIDSubsystem::PIDSubsystem(const wpi::Twine& name, double p, double i, double d)
+ : Subsystem(name) {
+ m_controller = std::make_shared<PIDController>(p, i, d, this, this);
+ AddChild("PIDController", m_controller);
+}
+
+PIDSubsystem::PIDSubsystem(const wpi::Twine& name, double p, double i, double d,
+ double f)
+ : Subsystem(name) {
+ m_controller = std::make_shared<PIDController>(p, i, d, f, this, this);
+ AddChild("PIDController", m_controller);
+}
+
+PIDSubsystem::PIDSubsystem(const wpi::Twine& name, double p, double i, double d,
+ double f, double period)
+ : Subsystem(name) {
+ m_controller =
+ std::make_shared<PIDController>(p, i, d, f, this, this, period);
+ AddChild("PIDController", m_controller);
+}
+
+PIDSubsystem::PIDSubsystem(double p, double i, double d)
+ : Subsystem("PIDSubsystem") {
+ m_controller = std::make_shared<PIDController>(p, i, d, this, this);
+ AddChild("PIDController", m_controller);
+}
+
+PIDSubsystem::PIDSubsystem(double p, double i, double d, double f)
+ : Subsystem("PIDSubsystem") {
+ m_controller = std::make_shared<PIDController>(p, i, d, f, this, this);
+ AddChild("PIDController", m_controller);
+}
+
+PIDSubsystem::PIDSubsystem(double p, double i, double d, double f,
+ double period)
+ : Subsystem("PIDSubsystem") {
+ m_controller =
+ std::make_shared<PIDController>(p, i, d, f, this, this, period);
+ AddChild("PIDController", m_controller);
+}
+
+void PIDSubsystem::Enable() { m_controller->Enable(); }
+
+void PIDSubsystem::Disable() { m_controller->Disable(); }
+
+void PIDSubsystem::PIDWrite(double output) { UsePIDOutput(output); }
+
+double PIDSubsystem::PIDGet() { return ReturnPIDInput(); }
+
+void PIDSubsystem::SetSetpoint(double setpoint) {
+ m_controller->SetSetpoint(setpoint);
+}
+
+void PIDSubsystem::SetSetpointRelative(double deltaSetpoint) {
+ SetSetpoint(GetSetpoint() + deltaSetpoint);
+}
+
+void PIDSubsystem::SetInputRange(double minimumInput, double maximumInput) {
+ m_controller->SetInputRange(minimumInput, maximumInput);
+}
+
+void PIDSubsystem::SetOutputRange(double minimumOutput, double maximumOutput) {
+ m_controller->SetOutputRange(minimumOutput, maximumOutput);
+}
+
+double PIDSubsystem::GetSetpoint() { return m_controller->GetSetpoint(); }
+
+double PIDSubsystem::GetPosition() { return ReturnPIDInput(); }
+
+double PIDSubsystem::GetRate() { return ReturnPIDInput(); }
+
+void PIDSubsystem::SetAbsoluteTolerance(double absValue) {
+ m_controller->SetAbsoluteTolerance(absValue);
+}
+
+void PIDSubsystem::SetPercentTolerance(double percent) {
+ m_controller->SetPercentTolerance(percent);
+}
+
+bool PIDSubsystem::OnTarget() const { return m_controller->OnTarget(); }
+
+std::shared_ptr<PIDController> PIDSubsystem::GetPIDController() {
+ return m_controller;
+}
diff --git a/wpilibc/src/main/native/cpp/commands/PrintCommand.cpp b/wpilibc/src/main/native/cpp/commands/PrintCommand.cpp
new file mode 100644
index 0000000..b4bea24
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/PrintCommand.cpp
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/commands/PrintCommand.h"
+
+#include <wpi/raw_ostream.h>
+
+using namespace frc;
+
+PrintCommand::PrintCommand(const wpi::Twine& message)
+ : InstantCommand("Print \"" + message + wpi::Twine('"')) {
+ m_message = message.str();
+}
+
+void PrintCommand::Initialize() { wpi::outs() << m_message << '\n'; }
diff --git a/wpilibc/src/main/native/cpp/commands/Scheduler.cpp b/wpilibc/src/main/native/cpp/commands/Scheduler.cpp
new file mode 100644
index 0000000..8a7af76
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/Scheduler.cpp
@@ -0,0 +1,243 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/commands/Scheduler.h"
+
+#include <algorithm>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <hal/HAL.h>
+#include <networktables/NetworkTableEntry.h>
+#include <wpi/mutex.h>
+
+#include "frc/WPIErrors.h"
+#include "frc/buttons/ButtonScheduler.h"
+#include "frc/commands/Command.h"
+#include "frc/commands/Subsystem.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+struct Scheduler::Impl {
+ void Remove(Command* command);
+ void ProcessCommandAddition(Command* command);
+
+ using SubsystemSet = std::set<Subsystem*>;
+ SubsystemSet subsystems;
+ wpi::mutex buttonsMutex;
+ using ButtonVector = std::vector<std::unique_ptr<ButtonScheduler>>;
+ ButtonVector buttons;
+ using CommandVector = std::vector<Command*>;
+ wpi::mutex additionsMutex;
+ CommandVector additions;
+ using CommandSet = std::set<Command*>;
+ CommandSet commands;
+ bool adding = false;
+ bool enabled = true;
+ std::vector<std::string> commandsBuf;
+ std::vector<double> idsBuf;
+ bool runningCommandsChanged = false;
+};
+
+Scheduler* Scheduler::GetInstance() {
+ static Scheduler instance;
+ return &instance;
+}
+
+void Scheduler::AddCommand(Command* command) {
+ std::lock_guard<wpi::mutex> lock(m_impl->additionsMutex);
+ if (std::find(m_impl->additions.begin(), m_impl->additions.end(), command) !=
+ m_impl->additions.end())
+ return;
+ m_impl->additions.push_back(command);
+}
+
+void Scheduler::AddButton(ButtonScheduler* button) {
+ std::lock_guard<wpi::mutex> lock(m_impl->buttonsMutex);
+ m_impl->buttons.emplace_back(button);
+}
+
+void Scheduler::RegisterSubsystem(Subsystem* subsystem) {
+ if (subsystem == nullptr) {
+ wpi_setWPIErrorWithContext(NullParameter, "subsystem");
+ return;
+ }
+ m_impl->subsystems.insert(subsystem);
+}
+
+void Scheduler::Run() {
+ // Get button input (going backwards preserves button priority)
+ {
+ if (!m_impl->enabled) return;
+
+ std::lock_guard<wpi::mutex> lock(m_impl->buttonsMutex);
+ for (auto& button : m_impl->buttons) {
+ button->Execute();
+ }
+ }
+
+ // Call every subsystem's periodic method
+ for (auto& subsystem : m_impl->subsystems) {
+ subsystem->Periodic();
+ }
+
+ m_impl->runningCommandsChanged = false;
+
+ // Loop through the commands
+ for (auto cmdIter = m_impl->commands.begin();
+ cmdIter != m_impl->commands.end();) {
+ Command* command = *cmdIter;
+ // Increment before potentially removing to keep the iterator valid
+ ++cmdIter;
+ if (!command->Run()) {
+ Remove(command);
+ m_impl->runningCommandsChanged = true;
+ }
+ }
+
+ // Add the new things
+ {
+ std::lock_guard<wpi::mutex> lock(m_impl->additionsMutex);
+ for (auto& addition : m_impl->additions) {
+ // Check to make sure no adding during adding
+ if (m_impl->adding) {
+ wpi_setWPIErrorWithContext(IncompatibleState,
+ "Can not start command from cancel method");
+ } else {
+ m_impl->ProcessCommandAddition(addition);
+ }
+ }
+ m_impl->additions.clear();
+ }
+
+ // Add in the defaults
+ for (auto& subsystem : m_impl->subsystems) {
+ if (subsystem->GetCurrentCommand() == nullptr) {
+ if (m_impl->adding) {
+ wpi_setWPIErrorWithContext(IncompatibleState,
+ "Can not start command from cancel method");
+ } else {
+ m_impl->ProcessCommandAddition(subsystem->GetDefaultCommand());
+ }
+ }
+ subsystem->ConfirmCommand();
+ }
+}
+
+void Scheduler::Remove(Command* command) {
+ if (command == nullptr) {
+ wpi_setWPIErrorWithContext(NullParameter, "command");
+ return;
+ }
+
+ m_impl->Remove(command);
+}
+
+void Scheduler::RemoveAll() {
+ while (m_impl->commands.size() > 0) {
+ Remove(*m_impl->commands.begin());
+ }
+}
+
+void Scheduler::ResetAll() {
+ RemoveAll();
+ m_impl->subsystems.clear();
+ m_impl->buttons.clear();
+ m_impl->additions.clear();
+ m_impl->commands.clear();
+}
+
+void Scheduler::SetEnabled(bool enabled) { m_impl->enabled = enabled; }
+
+void Scheduler::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Scheduler");
+ auto namesEntry = builder.GetEntry("Names");
+ auto idsEntry = builder.GetEntry("Ids");
+ auto cancelEntry = builder.GetEntry("Cancel");
+ builder.SetUpdateTable([=]() {
+ // Get the list of possible commands to cancel
+ auto new_toCancel = cancelEntry.GetValue();
+ wpi::ArrayRef<double> toCancel;
+ if (new_toCancel) toCancel = new_toCancel->GetDoubleArray();
+
+ // Cancel commands whose cancel buttons were pressed on the SmartDashboard
+ if (!toCancel.empty()) {
+ for (auto& command : m_impl->commands) {
+ for (const auto& cancelled : toCancel) {
+ if (command->GetID() == cancelled) {
+ command->Cancel();
+ }
+ }
+ }
+ nt::NetworkTableEntry(cancelEntry).SetDoubleArray({});
+ }
+
+ // Set the running commands
+ if (m_impl->runningCommandsChanged) {
+ m_impl->commandsBuf.resize(0);
+ m_impl->idsBuf.resize(0);
+ for (const auto& command : m_impl->commands) {
+ m_impl->commandsBuf.emplace_back(command->GetName());
+ m_impl->idsBuf.emplace_back(command->GetID());
+ }
+ nt::NetworkTableEntry(namesEntry).SetStringArray(m_impl->commandsBuf);
+ nt::NetworkTableEntry(idsEntry).SetDoubleArray(m_impl->idsBuf);
+ }
+ });
+}
+
+Scheduler::Scheduler() : m_impl(new Impl) {
+ HAL_Report(HALUsageReporting::kResourceType_Command,
+ HALUsageReporting::kCommand_Scheduler);
+ SetName("Scheduler");
+}
+
+Scheduler::~Scheduler() {}
+
+void Scheduler::Impl::Remove(Command* command) {
+ if (!commands.erase(command)) return;
+
+ for (auto&& requirement : command->GetRequirements()) {
+ requirement->SetCurrentCommand(nullptr);
+ }
+
+ command->Removed();
+}
+
+void Scheduler::Impl::ProcessCommandAddition(Command* command) {
+ if (command == nullptr) return;
+
+ // Only add if not already in
+ auto found = commands.find(command);
+ if (found == commands.end()) {
+ // Check that the requirements can be had
+ const auto& requirements = command->GetRequirements();
+ for (const auto& requirement : requirements) {
+ if (requirement->GetCurrentCommand() != nullptr &&
+ !requirement->GetCurrentCommand()->IsInterruptible())
+ return;
+ }
+
+ // Give it the requirements
+ adding = true;
+ for (auto&& requirement : requirements) {
+ if (requirement->GetCurrentCommand() != nullptr) {
+ requirement->GetCurrentCommand()->Cancel();
+ Remove(requirement->GetCurrentCommand());
+ }
+ requirement->SetCurrentCommand(command);
+ }
+ adding = false;
+
+ commands.insert(command);
+
+ command->StartRunning();
+ runningCommandsChanged = true;
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/commands/StartCommand.cpp b/wpilibc/src/main/native/cpp/commands/StartCommand.cpp
new file mode 100644
index 0000000..8884124
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/StartCommand.cpp
@@ -0,0 +1,17 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/commands/StartCommand.h"
+
+using namespace frc;
+
+StartCommand::StartCommand(Command* commandToStart)
+ : InstantCommand("StartCommand") {
+ m_commandToFork = commandToStart;
+}
+
+void StartCommand::Initialize() { m_commandToFork->Start(); }
diff --git a/wpilibc/src/main/native/cpp/commands/Subsystem.cpp b/wpilibc/src/main/native/cpp/commands/Subsystem.cpp
new file mode 100644
index 0000000..308642f
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/Subsystem.cpp
@@ -0,0 +1,114 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/commands/Subsystem.h"
+
+#include "frc/WPIErrors.h"
+#include "frc/commands/Command.h"
+#include "frc/commands/Scheduler.h"
+#include "frc/livewindow/LiveWindow.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+Subsystem::Subsystem(const wpi::Twine& name) {
+ SetName(name, name);
+ Scheduler::GetInstance()->RegisterSubsystem(this);
+}
+
+void Subsystem::SetDefaultCommand(Command* command) {
+ if (command == nullptr) {
+ m_defaultCommand = nullptr;
+ } else {
+ const auto& reqs = command->GetRequirements();
+ if (std::find(reqs.begin(), reqs.end(), this) == reqs.end()) {
+ wpi_setWPIErrorWithContext(
+ CommandIllegalUse, "A default command must require the subsystem");
+ return;
+ }
+
+ m_defaultCommand = command;
+ }
+}
+
+Command* Subsystem::GetDefaultCommand() {
+ if (!m_initializedDefaultCommand) {
+ m_initializedDefaultCommand = true;
+ InitDefaultCommand();
+ }
+ return m_defaultCommand;
+}
+
+wpi::StringRef Subsystem::GetDefaultCommandName() {
+ Command* defaultCommand = GetDefaultCommand();
+ if (defaultCommand) {
+ return defaultCommand->GetName();
+ } else {
+ return wpi::StringRef();
+ }
+}
+
+void Subsystem::SetCurrentCommand(Command* command) {
+ m_currentCommand = command;
+ m_currentCommandChanged = true;
+}
+
+Command* Subsystem::GetCurrentCommand() const { return m_currentCommand; }
+
+wpi::StringRef Subsystem::GetCurrentCommandName() const {
+ Command* currentCommand = GetCurrentCommand();
+ if (currentCommand) {
+ return currentCommand->GetName();
+ } else {
+ return wpi::StringRef();
+ }
+}
+
+void Subsystem::Periodic() {}
+
+void Subsystem::InitDefaultCommand() {}
+
+void Subsystem::AddChild(const wpi::Twine& name,
+ std::shared_ptr<Sendable> child) {
+ AddChild(name, *child);
+}
+
+void Subsystem::AddChild(const wpi::Twine& name, Sendable* child) {
+ AddChild(name, *child);
+}
+
+void Subsystem::AddChild(const wpi::Twine& name, Sendable& child) {
+ child.SetName(GetSubsystem(), name);
+ LiveWindow::GetInstance()->Add(&child);
+}
+
+void Subsystem::AddChild(std::shared_ptr<Sendable> child) { AddChild(*child); }
+
+void Subsystem::AddChild(Sendable* child) { AddChild(*child); }
+
+void Subsystem::AddChild(Sendable& child) {
+ child.SetSubsystem(GetSubsystem());
+ LiveWindow::GetInstance()->Add(&child);
+}
+
+void Subsystem::ConfirmCommand() {
+ if (m_currentCommandChanged) m_currentCommandChanged = false;
+}
+
+void Subsystem::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("Subsystem");
+
+ builder.AddBooleanProperty(
+ ".hasDefault", [=]() { return m_defaultCommand != nullptr; }, nullptr);
+ builder.AddStringProperty(".default",
+ [=]() { return GetDefaultCommandName(); }, nullptr);
+
+ builder.AddBooleanProperty(
+ ".hasCommand", [=]() { return m_currentCommand != nullptr; }, nullptr);
+ builder.AddStringProperty(".command",
+ [=]() { return GetCurrentCommandName(); }, nullptr);
+}
diff --git a/wpilibc/src/main/native/cpp/commands/TimedCommand.cpp b/wpilibc/src/main/native/cpp/commands/TimedCommand.cpp
new file mode 100644
index 0000000..122751a
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/TimedCommand.cpp
@@ -0,0 +1,24 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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 "frc/commands/TimedCommand.h"
+
+using namespace frc;
+
+TimedCommand::TimedCommand(const wpi::Twine& name, double timeout)
+ : Command(name, timeout) {}
+
+TimedCommand::TimedCommand(double timeout) : Command(timeout) {}
+
+TimedCommand::TimedCommand(const wpi::Twine& name, double timeout,
+ Subsystem& subsystem)
+ : Command(name, timeout, subsystem) {}
+
+TimedCommand::TimedCommand(double timeout, Subsystem& subsystem)
+ : Command(timeout, subsystem) {}
+
+bool TimedCommand::IsFinished() { return IsTimedOut(); }
diff --git a/wpilibc/src/main/native/cpp/commands/WaitCommand.cpp b/wpilibc/src/main/native/cpp/commands/WaitCommand.cpp
new file mode 100644
index 0000000..225d95b
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/WaitCommand.cpp
@@ -0,0 +1,16 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/commands/WaitCommand.h"
+
+using namespace frc;
+
+WaitCommand::WaitCommand(double timeout)
+ : TimedCommand("Wait(" + std::to_string(timeout) + ")", timeout) {}
+
+WaitCommand::WaitCommand(const wpi::Twine& name, double timeout)
+ : TimedCommand(name, timeout) {}
diff --git a/wpilibc/src/main/native/cpp/commands/WaitForChildren.cpp b/wpilibc/src/main/native/cpp/commands/WaitForChildren.cpp
new file mode 100644
index 0000000..5c99c1b
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/WaitForChildren.cpp
@@ -0,0 +1,22 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/commands/WaitForChildren.h"
+
+#include "frc/commands/CommandGroup.h"
+
+using namespace frc;
+
+WaitForChildren::WaitForChildren(double timeout)
+ : Command("WaitForChildren", timeout) {}
+
+WaitForChildren::WaitForChildren(const wpi::Twine& name, double timeout)
+ : Command(name, timeout) {}
+
+bool WaitForChildren::IsFinished() {
+ return GetGroup() == nullptr || GetGroup()->GetSize() == 0;
+}
diff --git a/wpilibc/src/main/native/cpp/commands/WaitUntilCommand.cpp b/wpilibc/src/main/native/cpp/commands/WaitUntilCommand.cpp
new file mode 100644
index 0000000..6e24b6b
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/commands/WaitUntilCommand.cpp
@@ -0,0 +1,24 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/commands/WaitUntilCommand.h"
+
+#include "frc/Timer.h"
+
+using namespace frc;
+
+WaitUntilCommand::WaitUntilCommand(double time)
+ : Command("WaitUntilCommand", time) {
+ m_time = time;
+}
+
+WaitUntilCommand::WaitUntilCommand(const wpi::Twine& name, double time)
+ : Command(name, time) {
+ m_time = time;
+}
+
+bool WaitUntilCommand::IsFinished() { return Timer::GetMatchTime() >= m_time; }
diff --git a/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp b/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp
new file mode 100644
index 0000000..5ad65b8
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp
@@ -0,0 +1,225 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/drive/DifferentialDrive.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include <hal/HAL.h>
+
+#include "frc/SpeedController.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+DifferentialDrive::DifferentialDrive(SpeedController& leftMotor,
+ SpeedController& rightMotor)
+ : m_leftMotor(leftMotor), m_rightMotor(rightMotor) {
+ AddChild(&m_leftMotor);
+ AddChild(&m_rightMotor);
+ static int instances = 0;
+ ++instances;
+ SetName("DifferentialDrive", instances);
+}
+
+void DifferentialDrive::ArcadeDrive(double xSpeed, double zRotation,
+ bool squareInputs) {
+ static bool reported = false;
+ if (!reported) {
+ HAL_Report(HALUsageReporting::kResourceType_RobotDrive, 2,
+ HALUsageReporting::kRobotDrive2_DifferentialArcade);
+ reported = true;
+ }
+
+ xSpeed = Limit(xSpeed);
+ xSpeed = ApplyDeadband(xSpeed, m_deadband);
+
+ zRotation = Limit(zRotation);
+ zRotation = ApplyDeadband(zRotation, m_deadband);
+
+ // Square the inputs (while preserving the sign) to increase fine control
+ // while permitting full power.
+ if (squareInputs) {
+ xSpeed = std::copysign(xSpeed * xSpeed, xSpeed);
+ zRotation = std::copysign(zRotation * zRotation, zRotation);
+ }
+
+ double leftMotorOutput;
+ double rightMotorOutput;
+
+ double maxInput =
+ std::copysign(std::max(std::abs(xSpeed), std::abs(zRotation)), xSpeed);
+
+ if (xSpeed >= 0.0) {
+ // First quadrant, else second quadrant
+ if (zRotation >= 0.0) {
+ leftMotorOutput = maxInput;
+ rightMotorOutput = xSpeed - zRotation;
+ } else {
+ leftMotorOutput = xSpeed + zRotation;
+ rightMotorOutput = maxInput;
+ }
+ } else {
+ // Third quadrant, else fourth quadrant
+ if (zRotation >= 0.0) {
+ leftMotorOutput = xSpeed + zRotation;
+ rightMotorOutput = maxInput;
+ } else {
+ leftMotorOutput = maxInput;
+ rightMotorOutput = xSpeed - zRotation;
+ }
+ }
+
+ m_leftMotor.Set(Limit(leftMotorOutput) * m_maxOutput);
+ m_rightMotor.Set(Limit(rightMotorOutput) * m_maxOutput *
+ m_rightSideInvertMultiplier);
+
+ Feed();
+}
+
+void DifferentialDrive::CurvatureDrive(double xSpeed, double zRotation,
+ bool isQuickTurn) {
+ static bool reported = false;
+ if (!reported) {
+ HAL_Report(HALUsageReporting::kResourceType_RobotDrive, 2,
+ HALUsageReporting::kRobotDrive2_DifferentialCurvature);
+ reported = true;
+ }
+
+ xSpeed = Limit(xSpeed);
+ xSpeed = ApplyDeadband(xSpeed, m_deadband);
+
+ zRotation = Limit(zRotation);
+ zRotation = ApplyDeadband(zRotation, m_deadband);
+
+ double angularPower;
+ bool overPower;
+
+ if (isQuickTurn) {
+ if (std::abs(xSpeed) < m_quickStopThreshold) {
+ m_quickStopAccumulator = (1 - m_quickStopAlpha) * m_quickStopAccumulator +
+ m_quickStopAlpha * Limit(zRotation) * 2;
+ }
+ overPower = true;
+ angularPower = zRotation;
+ } else {
+ overPower = false;
+ angularPower = std::abs(xSpeed) * zRotation - m_quickStopAccumulator;
+
+ if (m_quickStopAccumulator > 1) {
+ m_quickStopAccumulator -= 1;
+ } else if (m_quickStopAccumulator < -1) {
+ m_quickStopAccumulator += 1;
+ } else {
+ m_quickStopAccumulator = 0.0;
+ }
+ }
+
+ double leftMotorOutput = xSpeed + angularPower;
+ double rightMotorOutput = xSpeed - angularPower;
+
+ // If rotation is overpowered, reduce both outputs to within acceptable range
+ if (overPower) {
+ if (leftMotorOutput > 1.0) {
+ rightMotorOutput -= leftMotorOutput - 1.0;
+ leftMotorOutput = 1.0;
+ } else if (rightMotorOutput > 1.0) {
+ leftMotorOutput -= rightMotorOutput - 1.0;
+ rightMotorOutput = 1.0;
+ } else if (leftMotorOutput < -1.0) {
+ rightMotorOutput -= leftMotorOutput + 1.0;
+ leftMotorOutput = -1.0;
+ } else if (rightMotorOutput < -1.0) {
+ leftMotorOutput -= rightMotorOutput + 1.0;
+ rightMotorOutput = -1.0;
+ }
+ }
+
+ // Normalize the wheel speeds
+ double maxMagnitude =
+ std::max(std::abs(leftMotorOutput), std::abs(rightMotorOutput));
+ if (maxMagnitude > 1.0) {
+ leftMotorOutput /= maxMagnitude;
+ rightMotorOutput /= maxMagnitude;
+ }
+
+ m_leftMotor.Set(leftMotorOutput * m_maxOutput);
+ m_rightMotor.Set(rightMotorOutput * m_maxOutput *
+ m_rightSideInvertMultiplier);
+
+ Feed();
+}
+
+void DifferentialDrive::TankDrive(double leftSpeed, double rightSpeed,
+ bool squareInputs) {
+ static bool reported = false;
+ if (!reported) {
+ HAL_Report(HALUsageReporting::kResourceType_RobotDrive, 2,
+ HALUsageReporting::kRobotDrive2_DifferentialTank);
+ reported = true;
+ }
+
+ leftSpeed = Limit(leftSpeed);
+ leftSpeed = ApplyDeadband(leftSpeed, m_deadband);
+
+ rightSpeed = Limit(rightSpeed);
+ rightSpeed = ApplyDeadband(rightSpeed, m_deadband);
+
+ // Square the inputs (while preserving the sign) to increase fine control
+ // while permitting full power.
+ if (squareInputs) {
+ leftSpeed = std::copysign(leftSpeed * leftSpeed, leftSpeed);
+ rightSpeed = std::copysign(rightSpeed * rightSpeed, rightSpeed);
+ }
+
+ m_leftMotor.Set(leftSpeed * m_maxOutput);
+ m_rightMotor.Set(rightSpeed * m_maxOutput * m_rightSideInvertMultiplier);
+
+ Feed();
+}
+
+void DifferentialDrive::SetQuickStopThreshold(double threshold) {
+ m_quickStopThreshold = threshold;
+}
+
+void DifferentialDrive::SetQuickStopAlpha(double alpha) {
+ m_quickStopAlpha = alpha;
+}
+
+bool DifferentialDrive::IsRightSideInverted() const {
+ return m_rightSideInvertMultiplier == -1.0;
+}
+
+void DifferentialDrive::SetRightSideInverted(bool rightSideInverted) {
+ m_rightSideInvertMultiplier = rightSideInverted ? -1.0 : 1.0;
+}
+
+void DifferentialDrive::StopMotor() {
+ m_leftMotor.StopMotor();
+ m_rightMotor.StopMotor();
+ Feed();
+}
+
+void DifferentialDrive::GetDescription(wpi::raw_ostream& desc) const {
+ desc << "DifferentialDrive";
+}
+
+void DifferentialDrive::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("DifferentialDrive");
+ builder.SetActuator(true);
+ builder.SetSafeState([=] { StopMotor(); });
+ builder.AddDoubleProperty("Left Motor Speed",
+ [=]() { return m_leftMotor.Get(); },
+ [=](double value) { m_leftMotor.Set(value); });
+ builder.AddDoubleProperty(
+ "Right Motor Speed",
+ [=]() { return m_rightMotor.Get() * m_rightSideInvertMultiplier; },
+ [=](double value) {
+ m_rightMotor.Set(value * m_rightSideInvertMultiplier);
+ });
+}
diff --git a/wpilibc/src/main/native/cpp/drive/KilloughDrive.cpp b/wpilibc/src/main/native/cpp/drive/KilloughDrive.cpp
new file mode 100644
index 0000000..b1af5de
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/drive/KilloughDrive.cpp
@@ -0,0 +1,115 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/drive/KilloughDrive.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include <hal/HAL.h>
+
+#include "frc/SpeedController.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+constexpr double kPi = 3.14159265358979323846;
+
+KilloughDrive::KilloughDrive(SpeedController& leftMotor,
+ SpeedController& rightMotor,
+ SpeedController& backMotor)
+ : KilloughDrive(leftMotor, rightMotor, backMotor, kDefaultLeftMotorAngle,
+ kDefaultRightMotorAngle, kDefaultBackMotorAngle) {}
+
+KilloughDrive::KilloughDrive(SpeedController& leftMotor,
+ SpeedController& rightMotor,
+ SpeedController& backMotor, double leftMotorAngle,
+ double rightMotorAngle, double backMotorAngle)
+ : m_leftMotor(leftMotor), m_rightMotor(rightMotor), m_backMotor(backMotor) {
+ m_leftVec = {std::cos(leftMotorAngle * (kPi / 180.0)),
+ std::sin(leftMotorAngle * (kPi / 180.0))};
+ m_rightVec = {std::cos(rightMotorAngle * (kPi / 180.0)),
+ std::sin(rightMotorAngle * (kPi / 180.0))};
+ m_backVec = {std::cos(backMotorAngle * (kPi / 180.0)),
+ std::sin(backMotorAngle * (kPi / 180.0))};
+ AddChild(&m_leftMotor);
+ AddChild(&m_rightMotor);
+ AddChild(&m_backMotor);
+ static int instances = 0;
+ ++instances;
+ SetName("KilloughDrive", instances);
+}
+
+void KilloughDrive::DriveCartesian(double ySpeed, double xSpeed,
+ double zRotation, double gyroAngle) {
+ if (!reported) {
+ HAL_Report(HALUsageReporting::kResourceType_RobotDrive, 3,
+ HALUsageReporting::kRobotDrive2_KilloughCartesian);
+ reported = true;
+ }
+
+ ySpeed = Limit(ySpeed);
+ ySpeed = ApplyDeadband(ySpeed, m_deadband);
+
+ xSpeed = Limit(xSpeed);
+ xSpeed = ApplyDeadband(xSpeed, m_deadband);
+
+ // Compensate for gyro angle.
+ Vector2d input{ySpeed, xSpeed};
+ input.Rotate(-gyroAngle);
+
+ double wheelSpeeds[3];
+ wheelSpeeds[kLeft] = input.ScalarProject(m_leftVec) + zRotation;
+ wheelSpeeds[kRight] = input.ScalarProject(m_rightVec) + zRotation;
+ wheelSpeeds[kBack] = input.ScalarProject(m_backVec) + zRotation;
+
+ Normalize(wheelSpeeds);
+
+ m_leftMotor.Set(wheelSpeeds[kLeft] * m_maxOutput);
+ m_rightMotor.Set(wheelSpeeds[kRight] * m_maxOutput);
+ m_backMotor.Set(wheelSpeeds[kBack] * m_maxOutput);
+
+ Feed();
+}
+
+void KilloughDrive::DrivePolar(double magnitude, double angle,
+ double zRotation) {
+ if (!reported) {
+ HAL_Report(HALUsageReporting::kResourceType_RobotDrive, 3,
+ HALUsageReporting::kRobotDrive2_KilloughPolar);
+ reported = true;
+ }
+
+ DriveCartesian(magnitude * std::sin(angle * (kPi / 180.0)),
+ magnitude * std::cos(angle * (kPi / 180.0)), zRotation, 0.0);
+}
+
+void KilloughDrive::StopMotor() {
+ m_leftMotor.StopMotor();
+ m_rightMotor.StopMotor();
+ m_backMotor.StopMotor();
+ Feed();
+}
+
+void KilloughDrive::GetDescription(wpi::raw_ostream& desc) const {
+ desc << "KilloughDrive";
+}
+
+void KilloughDrive::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("KilloughDrive");
+ builder.SetActuator(true);
+ builder.SetSafeState([=] { StopMotor(); });
+ builder.AddDoubleProperty("Left Motor Speed",
+ [=]() { return m_leftMotor.Get(); },
+ [=](double value) { m_leftMotor.Set(value); });
+ builder.AddDoubleProperty("Right Motor Speed",
+ [=]() { return m_rightMotor.Get(); },
+ [=](double value) { m_rightMotor.Set(value); });
+ builder.AddDoubleProperty("Back Motor Speed",
+ [=]() { return m_backMotor.Get(); },
+ [=](double value) { m_backMotor.Set(value); });
+}
diff --git a/wpilibc/src/main/native/cpp/drive/MecanumDrive.cpp b/wpilibc/src/main/native/cpp/drive/MecanumDrive.cpp
new file mode 100644
index 0000000..c74ba19
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/drive/MecanumDrive.cpp
@@ -0,0 +1,130 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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 "frc/drive/MecanumDrive.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include <hal/HAL.h>
+
+#include "frc/SpeedController.h"
+#include "frc/drive/Vector2d.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+constexpr double kPi = 3.14159265358979323846;
+
+MecanumDrive::MecanumDrive(SpeedController& frontLeftMotor,
+ SpeedController& rearLeftMotor,
+ SpeedController& frontRightMotor,
+ SpeedController& rearRightMotor)
+ : m_frontLeftMotor(frontLeftMotor),
+ m_rearLeftMotor(rearLeftMotor),
+ m_frontRightMotor(frontRightMotor),
+ m_rearRightMotor(rearRightMotor) {
+ AddChild(&m_frontLeftMotor);
+ AddChild(&m_rearLeftMotor);
+ AddChild(&m_frontRightMotor);
+ AddChild(&m_rearRightMotor);
+ static int instances = 0;
+ ++instances;
+ SetName("MecanumDrive", instances);
+}
+
+void MecanumDrive::DriveCartesian(double ySpeed, double xSpeed,
+ double zRotation, double gyroAngle) {
+ if (!reported) {
+ HAL_Report(HALUsageReporting::kResourceType_RobotDrive, 4,
+ HALUsageReporting::kRobotDrive2_MecanumCartesian);
+ reported = true;
+ }
+
+ ySpeed = Limit(ySpeed);
+ ySpeed = ApplyDeadband(ySpeed, m_deadband);
+
+ xSpeed = Limit(xSpeed);
+ xSpeed = ApplyDeadband(xSpeed, m_deadband);
+
+ // Compensate for gyro angle.
+ Vector2d input{ySpeed, xSpeed};
+ input.Rotate(-gyroAngle);
+
+ double wheelSpeeds[4];
+ wheelSpeeds[kFrontLeft] = input.x + input.y + zRotation;
+ wheelSpeeds[kFrontRight] = -input.x + input.y - zRotation;
+ wheelSpeeds[kRearLeft] = -input.x + input.y + zRotation;
+ wheelSpeeds[kRearRight] = input.x + input.y - zRotation;
+
+ Normalize(wheelSpeeds);
+
+ m_frontLeftMotor.Set(wheelSpeeds[kFrontLeft] * m_maxOutput);
+ m_frontRightMotor.Set(wheelSpeeds[kFrontRight] * m_maxOutput *
+ m_rightSideInvertMultiplier);
+ m_rearLeftMotor.Set(wheelSpeeds[kRearLeft] * m_maxOutput);
+ m_rearRightMotor.Set(wheelSpeeds[kRearRight] * m_maxOutput *
+ m_rightSideInvertMultiplier);
+
+ Feed();
+}
+
+void MecanumDrive::DrivePolar(double magnitude, double angle,
+ double zRotation) {
+ if (!reported) {
+ HAL_Report(HALUsageReporting::kResourceType_RobotDrive, 4,
+ HALUsageReporting::kRobotDrive2_MecanumPolar);
+ reported = true;
+ }
+
+ DriveCartesian(magnitude * std::sin(angle * (kPi / 180.0)),
+ magnitude * std::cos(angle * (kPi / 180.0)), zRotation, 0.0);
+}
+
+bool MecanumDrive::IsRightSideInverted() const {
+ return m_rightSideInvertMultiplier == -1.0;
+}
+
+void MecanumDrive::SetRightSideInverted(bool rightSideInverted) {
+ m_rightSideInvertMultiplier = rightSideInverted ? -1.0 : 1.0;
+}
+
+void MecanumDrive::StopMotor() {
+ m_frontLeftMotor.StopMotor();
+ m_frontRightMotor.StopMotor();
+ m_rearLeftMotor.StopMotor();
+ m_rearRightMotor.StopMotor();
+ Feed();
+}
+
+void MecanumDrive::GetDescription(wpi::raw_ostream& desc) const {
+ desc << "MecanumDrive";
+}
+
+void MecanumDrive::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("MecanumDrive");
+ builder.SetActuator(true);
+ builder.SetSafeState([=] { StopMotor(); });
+ builder.AddDoubleProperty("Front Left Motor Speed",
+ [=]() { return m_frontLeftMotor.Get(); },
+ [=](double value) { m_frontLeftMotor.Set(value); });
+ builder.AddDoubleProperty(
+ "Front Right Motor Speed",
+ [=]() { return m_frontRightMotor.Get() * m_rightSideInvertMultiplier; },
+ [=](double value) {
+ m_frontRightMotor.Set(value * m_rightSideInvertMultiplier);
+ });
+ builder.AddDoubleProperty("Rear Left Motor Speed",
+ [=]() { return m_rearLeftMotor.Get(); },
+ [=](double value) { m_rearLeftMotor.Set(value); });
+ builder.AddDoubleProperty(
+ "Rear Right Motor Speed",
+ [=]() { return m_rearRightMotor.Get() * m_rightSideInvertMultiplier; },
+ [=](double value) {
+ m_rearRightMotor.Set(value * m_rightSideInvertMultiplier);
+ });
+}
diff --git a/wpilibc/src/main/native/cpp/drive/RobotDriveBase.cpp b/wpilibc/src/main/native/cpp/drive/RobotDriveBase.cpp
new file mode 100644
index 0000000..c22cb2a
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/drive/RobotDriveBase.cpp
@@ -0,0 +1,64 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/drive/RobotDriveBase.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstddef>
+
+#include <hal/HAL.h>
+
+#include "frc/Base.h"
+#include "frc/SpeedController.h"
+
+using namespace frc;
+
+RobotDriveBase::RobotDriveBase() { SetSafetyEnabled(true); }
+
+void RobotDriveBase::SetDeadband(double deadband) { m_deadband = deadband; }
+
+void RobotDriveBase::SetMaxOutput(double maxOutput) { m_maxOutput = maxOutput; }
+
+void RobotDriveBase::FeedWatchdog() { Feed(); }
+
+double RobotDriveBase::Limit(double value) {
+ if (value > 1.0) {
+ return 1.0;
+ }
+ if (value < -1.0) {
+ return -1.0;
+ }
+ return value;
+}
+
+double RobotDriveBase::ApplyDeadband(double value, double deadband) {
+ if (std::abs(value) > deadband) {
+ if (value > 0.0) {
+ return (value - deadband) / (1.0 - deadband);
+ } else {
+ return (value + deadband) / (1.0 - deadband);
+ }
+ } else {
+ return 0.0;
+ }
+}
+
+void RobotDriveBase::Normalize(wpi::MutableArrayRef<double> wheelSpeeds) {
+ double maxMagnitude = std::abs(wheelSpeeds[0]);
+ for (size_t i = 1; i < wheelSpeeds.size(); i++) {
+ double temp = std::abs(wheelSpeeds[i]);
+ if (maxMagnitude < temp) {
+ maxMagnitude = temp;
+ }
+ }
+ if (maxMagnitude > 1.0) {
+ for (size_t i = 0; i < wheelSpeeds.size(); i++) {
+ wheelSpeeds[i] = wheelSpeeds[i] / maxMagnitude;
+ }
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/drive/Vector2d.cpp b/wpilibc/src/main/native/cpp/drive/Vector2d.cpp
new file mode 100644
index 0000000..3d4b689
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/drive/Vector2d.cpp
@@ -0,0 +1,39 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/drive/Vector2d.h"
+
+#include <cmath>
+
+using namespace frc;
+
+constexpr double kPi = 3.14159265358979323846;
+
+Vector2d::Vector2d(double x, double y) {
+ this->x = x;
+ this->y = y;
+}
+
+void Vector2d::Rotate(double angle) {
+ double cosA = std::cos(angle * (kPi / 180.0));
+ double sinA = std::sin(angle * (kPi / 180.0));
+ double out[2];
+ out[0] = x * cosA - y * sinA;
+ out[1] = x * sinA + y * cosA;
+ x = out[0];
+ y = out[1];
+}
+
+double Vector2d::Dot(const Vector2d& vec) const {
+ return x * vec.x + y * vec.y;
+}
+
+double Vector2d::Magnitude() const { return std::sqrt(x * x + y * y); }
+
+double Vector2d::ScalarProject(const Vector2d& vec) const {
+ return Dot(vec) / vec.Magnitude();
+}
diff --git a/wpilibc/src/main/native/cpp/filters/Filter.cpp b/wpilibc/src/main/native/cpp/filters/Filter.cpp
new file mode 100644
index 0000000..c25d7af
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/filters/Filter.cpp
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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 "frc/filters/Filter.h"
+
+#include "frc/Base.h"
+
+using namespace frc;
+
+Filter::Filter(PIDSource& source)
+ : m_source(std::shared_ptr<PIDSource>(&source, NullDeleter<PIDSource>())) {}
+
+Filter::Filter(std::shared_ptr<PIDSource> source)
+ : m_source(std::move(source)) {}
+
+void Filter::SetPIDSourceType(PIDSourceType pidSource) {
+ m_source->SetPIDSourceType(pidSource);
+}
+
+PIDSourceType Filter::GetPIDSourceType() const {
+ return m_source->GetPIDSourceType();
+}
+
+double Filter::PIDGetSource() { return m_source->PIDGet(); }
diff --git a/wpilibc/src/main/native/cpp/filters/LinearDigitalFilter.cpp b/wpilibc/src/main/native/cpp/filters/LinearDigitalFilter.cpp
new file mode 100644
index 0000000..db4cebe
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/filters/LinearDigitalFilter.cpp
@@ -0,0 +1,122 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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 "frc/filters/LinearDigitalFilter.h"
+
+#include <cassert>
+#include <cmath>
+
+#include <hal/HAL.h>
+
+using namespace frc;
+
+LinearDigitalFilter::LinearDigitalFilter(PIDSource& source,
+ wpi::ArrayRef<double> ffGains,
+ wpi::ArrayRef<double> fbGains)
+ : Filter(source),
+ m_inputs(ffGains.size()),
+ m_outputs(fbGains.size()),
+ m_inputGains(ffGains),
+ m_outputGains(fbGains) {
+ static int instances = 0;
+ instances++;
+ HAL_Report(HALUsageReporting::kResourceType_LinearFilter, instances);
+}
+
+LinearDigitalFilter::LinearDigitalFilter(std::shared_ptr<PIDSource> source,
+ wpi::ArrayRef<double> ffGains,
+ wpi::ArrayRef<double> fbGains)
+ : Filter(source),
+ m_inputs(ffGains.size()),
+ m_outputs(fbGains.size()),
+ m_inputGains(ffGains),
+ m_outputGains(fbGains) {
+ static int instances = 0;
+ instances++;
+ HAL_Report(HALUsageReporting::kResourceType_LinearFilter, instances);
+}
+
+LinearDigitalFilter LinearDigitalFilter::SinglePoleIIR(PIDSource& source,
+ double timeConstant,
+ double period) {
+ double gain = std::exp(-period / timeConstant);
+ return LinearDigitalFilter(source, {1.0 - gain}, {-gain});
+}
+
+LinearDigitalFilter LinearDigitalFilter::HighPass(PIDSource& source,
+ double timeConstant,
+ double period) {
+ double gain = std::exp(-period / timeConstant);
+ return LinearDigitalFilter(source, {gain, -gain}, {-gain});
+}
+
+LinearDigitalFilter LinearDigitalFilter::MovingAverage(PIDSource& source,
+ int taps) {
+ assert(taps > 0);
+
+ std::vector<double> gains(taps, 1.0 / taps);
+ return LinearDigitalFilter(source, gains, {});
+}
+
+LinearDigitalFilter LinearDigitalFilter::SinglePoleIIR(
+ std::shared_ptr<PIDSource> source, double timeConstant, double period) {
+ double gain = std::exp(-period / timeConstant);
+ return LinearDigitalFilter(std::move(source), {1.0 - gain}, {-gain});
+}
+
+LinearDigitalFilter LinearDigitalFilter::HighPass(
+ std::shared_ptr<PIDSource> source, double timeConstant, double period) {
+ double gain = std::exp(-period / timeConstant);
+ return LinearDigitalFilter(std::move(source), {gain, -gain}, {-gain});
+}
+
+LinearDigitalFilter LinearDigitalFilter::MovingAverage(
+ std::shared_ptr<PIDSource> source, int taps) {
+ assert(taps > 0);
+
+ std::vector<double> gains(taps, 1.0 / taps);
+ return LinearDigitalFilter(std::move(source), gains, {});
+}
+
+double LinearDigitalFilter::Get() const {
+ double retVal = 0.0;
+
+ // Calculate the new value
+ for (size_t i = 0; i < m_inputGains.size(); i++) {
+ retVal += m_inputs[i] * m_inputGains[i];
+ }
+ for (size_t i = 0; i < m_outputGains.size(); i++) {
+ retVal -= m_outputs[i] * m_outputGains[i];
+ }
+
+ return retVal;
+}
+
+void LinearDigitalFilter::Reset() {
+ m_inputs.reset();
+ m_outputs.reset();
+}
+
+double LinearDigitalFilter::PIDGet() {
+ double retVal = 0.0;
+
+ // Rotate the inputs
+ m_inputs.push_front(PIDGetSource());
+
+ // Calculate the new value
+ for (size_t i = 0; i < m_inputGains.size(); i++) {
+ retVal += m_inputs[i] * m_inputGains[i];
+ }
+ for (size_t i = 0; i < m_outputGains.size(); i++) {
+ retVal -= m_outputs[i] * m_outputGains[i];
+ }
+
+ // Rotate the outputs
+ m_outputs.push_front(retVal);
+
+ return retVal;
+}
diff --git a/wpilibc/src/main/native/cpp/interfaces/Potentiometer.cpp b/wpilibc/src/main/native/cpp/interfaces/Potentiometer.cpp
new file mode 100644
index 0000000..44f4aab
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/interfaces/Potentiometer.cpp
@@ -0,0 +1,18 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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 "frc/interfaces/Potentiometer.h"
+
+#include "frc/Utility.h"
+
+using namespace frc;
+
+void Potentiometer::SetPIDSourceType(PIDSourceType pidSource) {
+ if (wpi_assert(pidSource == PIDSourceType::kDisplacement)) {
+ m_pidSource = pidSource;
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/livewindow/LiveWindow.cpp b/wpilibc/src/main/native/cpp/livewindow/LiveWindow.cpp
new file mode 100644
index 0000000..135d044
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/livewindow/LiveWindow.cpp
@@ -0,0 +1,238 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2012-2018 FIRST. 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 "frc/livewindow/LiveWindow.h"
+
+#include <algorithm>
+
+#include <networktables/NetworkTable.h>
+#include <networktables/NetworkTableEntry.h>
+#include <networktables/NetworkTableInstance.h>
+#include <wpi/DenseMap.h>
+#include <wpi/SmallString.h>
+#include <wpi/mutex.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/commands/Scheduler.h"
+#include "frc/smartdashboard/SendableBuilderImpl.h"
+
+using namespace frc;
+
+using wpi::Twine;
+
+struct LiveWindow::Impl {
+ Impl();
+
+ struct Component {
+ std::shared_ptr<Sendable> sendable;
+ Sendable* parent = nullptr;
+ SendableBuilderImpl builder;
+ bool firstTime = true;
+ bool telemetryEnabled = true;
+ };
+
+ wpi::mutex mutex;
+
+ wpi::DenseMap<void*, Component> components;
+
+ std::shared_ptr<nt::NetworkTable> liveWindowTable;
+ std::shared_ptr<nt::NetworkTable> statusTable;
+ nt::NetworkTableEntry enabledEntry;
+
+ bool startLiveWindow = false;
+ bool liveWindowEnabled = false;
+ bool telemetryEnabled = true;
+};
+
+LiveWindow::Impl::Impl()
+ : liveWindowTable(
+ nt::NetworkTableInstance::GetDefault().GetTable("LiveWindow")) {
+ statusTable = liveWindowTable->GetSubTable(".status");
+ enabledEntry = statusTable->GetEntry("LW Enabled");
+}
+
+LiveWindow* LiveWindow::GetInstance() {
+ static LiveWindow instance;
+ return &instance;
+}
+
+void LiveWindow::Run() { UpdateValues(); }
+
+void LiveWindow::AddSensor(const wpi::Twine& subsystem, const wpi::Twine& name,
+ Sendable* component) {
+ Add(component);
+ component->SetName(subsystem, name);
+}
+
+void LiveWindow::AddSensor(const wpi::Twine& subsystem, const wpi::Twine& name,
+ Sendable& component) {
+ Add(&component);
+ component.SetName(subsystem, name);
+}
+
+void LiveWindow::AddSensor(const wpi::Twine& subsystem, const wpi::Twine& name,
+ std::shared_ptr<Sendable> component) {
+ Add(component);
+ component->SetName(subsystem, name);
+}
+
+void LiveWindow::AddActuator(const wpi::Twine& subsystem,
+ const wpi::Twine& name, Sendable* component) {
+ Add(component);
+ component->SetName(subsystem, name);
+}
+
+void LiveWindow::AddActuator(const wpi::Twine& subsystem,
+ const wpi::Twine& name, Sendable& component) {
+ Add(&component);
+ component.SetName(subsystem, name);
+}
+
+void LiveWindow::AddActuator(const wpi::Twine& subsystem,
+ const wpi::Twine& name,
+ std::shared_ptr<Sendable> component) {
+ Add(component);
+ component->SetName(subsystem, name);
+}
+
+void LiveWindow::AddSensor(const wpi::Twine& type, int channel,
+ Sendable* component) {
+ Add(component);
+ component->SetName("Ungrouped",
+ type + Twine('[') + Twine(channel) + Twine(']'));
+}
+
+void LiveWindow::AddActuator(const wpi::Twine& type, int channel,
+ Sendable* component) {
+ Add(component);
+ component->SetName("Ungrouped",
+ type + Twine('[') + Twine(channel) + Twine(']'));
+}
+
+void LiveWindow::AddActuator(const wpi::Twine& type, int module, int channel,
+ Sendable* component) {
+ Add(component);
+ component->SetName("Ungrouped", type + Twine('[') + Twine(module) +
+ Twine(',') + Twine(channel) + Twine(']'));
+}
+
+void LiveWindow::Add(std::shared_ptr<Sendable> sendable) {
+ std::lock_guard<wpi::mutex> lock(m_impl->mutex);
+ auto& comp = m_impl->components[sendable.get()];
+ comp.sendable = sendable;
+}
+
+void LiveWindow::Add(Sendable* sendable) {
+ Add(std::shared_ptr<Sendable>(sendable, NullDeleter<Sendable>()));
+}
+
+void LiveWindow::AddChild(Sendable* parent, std::shared_ptr<Sendable> child) {
+ AddChild(parent, child.get());
+}
+
+void LiveWindow::AddChild(Sendable* parent, void* child) {
+ std::lock_guard<wpi::mutex> lock(m_impl->mutex);
+ auto& comp = m_impl->components[child];
+ comp.parent = parent;
+ comp.telemetryEnabled = false;
+}
+
+void LiveWindow::Remove(Sendable* sendable) {
+ std::lock_guard<wpi::mutex> lock(m_impl->mutex);
+ m_impl->components.erase(sendable);
+}
+
+void LiveWindow::EnableTelemetry(Sendable* sendable) {
+ std::lock_guard<wpi::mutex> lock(m_impl->mutex);
+ // Re-enable global setting in case DisableAllTelemetry() was called.
+ m_impl->telemetryEnabled = true;
+ auto i = m_impl->components.find(sendable);
+ if (i != m_impl->components.end()) i->getSecond().telemetryEnabled = true;
+}
+
+void LiveWindow::DisableTelemetry(Sendable* sendable) {
+ std::lock_guard<wpi::mutex> lock(m_impl->mutex);
+ auto i = m_impl->components.find(sendable);
+ if (i != m_impl->components.end()) i->getSecond().telemetryEnabled = false;
+}
+
+void LiveWindow::DisableAllTelemetry() {
+ std::lock_guard<wpi::mutex> lock(m_impl->mutex);
+ m_impl->telemetryEnabled = false;
+ for (auto& i : m_impl->components) i.getSecond().telemetryEnabled = false;
+}
+
+bool LiveWindow::IsEnabled() const {
+ std::lock_guard<wpi::mutex> lock(m_impl->mutex);
+ return m_impl->liveWindowEnabled;
+}
+
+void LiveWindow::SetEnabled(bool enabled) {
+ std::lock_guard<wpi::mutex> lock(m_impl->mutex);
+ if (m_impl->liveWindowEnabled == enabled) return;
+ Scheduler* scheduler = Scheduler::GetInstance();
+ m_impl->startLiveWindow = enabled;
+ m_impl->liveWindowEnabled = enabled;
+ // Force table generation now to make sure everything is defined
+ UpdateValuesUnsafe();
+ if (enabled) {
+ scheduler->SetEnabled(false);
+ scheduler->RemoveAll();
+ } else {
+ for (auto& i : m_impl->components) {
+ i.getSecond().builder.StopLiveWindowMode();
+ }
+ scheduler->SetEnabled(true);
+ }
+ m_impl->enabledEntry.SetBoolean(enabled);
+}
+
+void LiveWindow::UpdateValues() {
+ std::lock_guard<wpi::mutex> lock(m_impl->mutex);
+ UpdateValuesUnsafe();
+}
+
+void LiveWindow::UpdateValuesUnsafe() {
+ // Only do this if either LiveWindow mode or telemetry is enabled.
+ if (!m_impl->liveWindowEnabled && !m_impl->telemetryEnabled) return;
+
+ for (auto& i : m_impl->components) {
+ auto& comp = i.getSecond();
+ if (comp.sendable && !comp.parent &&
+ (m_impl->liveWindowEnabled || comp.telemetryEnabled)) {
+ if (comp.firstTime) {
+ // By holding off creating the NetworkTable entries, it allows the
+ // components to be redefined. This allows default sensor and actuator
+ // values to be created that are replaced with the custom names from
+ // users calling setName.
+ auto name = comp.sendable->GetName();
+ if (name.empty()) continue;
+ auto subsystem = comp.sendable->GetSubsystem();
+ auto ssTable = m_impl->liveWindowTable->GetSubTable(subsystem);
+ std::shared_ptr<NetworkTable> table;
+ // Treat name==subsystem as top level of subsystem
+ if (name == subsystem)
+ table = ssTable;
+ else
+ table = ssTable->GetSubTable(name);
+ table->GetEntry(".name").SetString(name);
+ comp.builder.SetTable(table);
+ comp.sendable->InitSendable(comp.builder);
+ ssTable->GetEntry(".type").SetString("LW Subsystem");
+
+ comp.firstTime = false;
+ }
+
+ if (m_impl->startLiveWindow) comp.builder.StartLiveWindowMode();
+ comp.builder.UpdateTable();
+ }
+ }
+
+ m_impl->startLiveWindow = false;
+}
+
+LiveWindow::LiveWindow() : m_impl(new Impl) {}
diff --git a/wpilibc/src/main/native/cpp/livewindow/LiveWindowSendable.cpp b/wpilibc/src/main/native/cpp/livewindow/LiveWindowSendable.cpp
new file mode 100644
index 0000000..7f03f52
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/livewindow/LiveWindowSendable.cpp
@@ -0,0 +1,24 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/livewindow/LiveWindowSendable.h"
+
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+std::string LiveWindowSendable::GetName() const { return std::string(); }
+
+void LiveWindowSendable::SetName(const wpi::Twine&) {}
+
+std::string LiveWindowSendable::GetSubsystem() const { return std::string(); }
+
+void LiveWindowSendable::SetSubsystem(const wpi::Twine&) {}
+
+void LiveWindowSendable::InitSendable(SendableBuilder& builder) {
+ builder.SetUpdateTable([=]() { UpdateTable(); });
+}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/BuiltInLayouts.cpp b/wpilibc/src/main/native/cpp/shuffleboard/BuiltInLayouts.cpp
new file mode 100644
index 0000000..5d09310
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/BuiltInLayouts.cpp
@@ -0,0 +1,13 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/BuiltInLayouts.h"
+
+using namespace frc;
+
+const LayoutType BuiltInLayouts::kList{"List Layout"};
+const LayoutType BuiltInLayouts::kGrid{"Grid Layout"};
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/BuiltInWidgets.cpp b/wpilibc/src/main/native/cpp/shuffleboard/BuiltInWidgets.cpp
new file mode 100644
index 0000000..df6a1f3
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/BuiltInWidgets.cpp
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/BuiltInWidgets.h"
+
+using namespace frc;
+
+const WidgetType BuiltInWidgets::kTextView{"Text View"};
+const WidgetType BuiltInWidgets::kNumberSlider{"Number Slider"};
+const WidgetType BuiltInWidgets::kNumberBar{"Number Bar"};
+const WidgetType BuiltInWidgets::kDial{"Simple Dial"};
+const WidgetType BuiltInWidgets::kGraph{"Graph"};
+const WidgetType BuiltInWidgets::kBooleanBox{"Boolean Box"};
+const WidgetType BuiltInWidgets::kToggleButton{"Toggle Button"};
+const WidgetType BuiltInWidgets::kToggleSwitch{"Toggle Switch"};
+const WidgetType BuiltInWidgets::kVoltageView{"Voltage View"};
+const WidgetType BuiltInWidgets::kPowerDistributionPanel{"PDP"};
+const WidgetType BuiltInWidgets::kComboBoxChooser{"ComboBox Chooser"};
+const WidgetType BuiltInWidgets::kSplitButtonChooser{"Split Button Chooser"};
+const WidgetType BuiltInWidgets::kEncoder{"Encoder"};
+const WidgetType BuiltInWidgets::kSpeedController{"Speed Controller"};
+const WidgetType BuiltInWidgets::kCommand{"Command"};
+const WidgetType BuiltInWidgets::kPIDCommand{"PID Command"};
+const WidgetType BuiltInWidgets::kPIDController{"PID Controller"};
+const WidgetType BuiltInWidgets::kAccelerometer{"Accelerometer"};
+const WidgetType BuiltInWidgets::k3AxisAccelerometer{"3-Axis Accelerometer"};
+const WidgetType BuiltInWidgets::kGyro{"Gyro"};
+const WidgetType BuiltInWidgets::kRelay{"Relay"};
+const WidgetType BuiltInWidgets::kDifferentialDrive{"Differential Drivebase"};
+const WidgetType BuiltInWidgets::kMecanumDrive{"Mecanum Drivebase"};
+const WidgetType BuiltInWidgets::kCameraStream{"Camera Stream"};
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ComplexWidget.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ComplexWidget.cpp
new file mode 100644
index 0000000..19e17bb
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/ComplexWidget.cpp
@@ -0,0 +1,42 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/ComplexWidget.h"
+
+#include "frc/smartdashboard/Sendable.h"
+
+using namespace frc;
+
+ComplexWidget::ComplexWidget(ShuffleboardContainer& parent,
+ const wpi::Twine& title, Sendable& sendable)
+ : ShuffleboardValue(title),
+ ShuffleboardWidget(parent, title),
+ m_sendable(sendable) {}
+
+void ComplexWidget::EnableIfActuator() {
+ if (m_builder.IsActuator()) {
+ m_builder.StartLiveWindowMode();
+ }
+}
+
+void ComplexWidget::DisableIfActuator() {
+ if (m_builder.IsActuator()) {
+ m_builder.StopLiveWindowMode();
+ }
+}
+
+void ComplexWidget::BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
+ std::shared_ptr<nt::NetworkTable> metaTable) {
+ BuildMetadata(metaTable);
+ if (!m_builderInit) {
+ m_builder.SetTable(parentTable->GetSubTable(GetTitle()));
+ m_sendable.InitSendable(m_builder);
+ m_builder.StartListeners();
+ m_builderInit = true;
+ }
+ m_builder.UpdateTable();
+}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/LayoutType.cpp b/wpilibc/src/main/native/cpp/shuffleboard/LayoutType.cpp
new file mode 100644
index 0000000..a21cad9
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/LayoutType.cpp
@@ -0,0 +1,12 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/LayoutType.h"
+
+using namespace frc;
+
+wpi::StringRef LayoutType::GetLayoutName() const { return m_layoutName; }
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/RecordingController.cpp b/wpilibc/src/main/native/cpp/shuffleboard/RecordingController.cpp
new file mode 100644
index 0000000..294be79
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/RecordingController.cpp
@@ -0,0 +1,50 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/RecordingController.h"
+
+#include "frc/DriverStation.h"
+
+using namespace frc;
+using namespace frc::detail;
+
+RecordingController::RecordingController(nt::NetworkTableInstance ntInstance)
+ : m_recordingControlEntry(), m_recordingFileNameFormatEntry() {
+ m_recordingControlEntry =
+ ntInstance.GetEntry("/Shuffleboard/.recording/RecordData");
+ m_recordingFileNameFormatEntry =
+ ntInstance.GetEntry("/Shuffleboard/.recording/FileNameFormat");
+ m_eventsTable = ntInstance.GetTable("/Shuffleboard/.recording/events");
+}
+
+void RecordingController::StartRecording() {
+ m_recordingControlEntry.SetBoolean(true);
+}
+
+void RecordingController::StopRecording() {
+ m_recordingControlEntry.SetBoolean(false);
+}
+
+void RecordingController::SetRecordingFileNameFormat(wpi::StringRef format) {
+ m_recordingFileNameFormatEntry.SetString(format);
+}
+
+void RecordingController::ClearRecordingFileNameFormat() {
+ m_recordingFileNameFormatEntry.Delete();
+}
+
+void RecordingController::AddEventMarker(
+ wpi::StringRef name, wpi::StringRef description,
+ ShuffleboardEventImportance importance) {
+ if (name.empty()) {
+ DriverStation::ReportError("Shuffleboard event name was not specified");
+ return;
+ }
+ auto arr = wpi::ArrayRef<std::string>{
+ description, ShuffleboardEventImportanceName(importance)};
+ m_eventsTable->GetSubTable(name)->GetEntry("Info").SetStringArray(arr);
+}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/SendableCameraWrapper.cpp b/wpilibc/src/main/native/cpp/shuffleboard/SendableCameraWrapper.cpp
new file mode 100644
index 0000000..87d7e9d
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/SendableCameraWrapper.cpp
@@ -0,0 +1,46 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/SendableCameraWrapper.h"
+
+#include <cscore_oo.h>
+#include <wpi/DenseMap.h>
+
+#include "frc/smartdashboard/SendableBuilder.h"
+
+using namespace frc;
+
+namespace {
+constexpr const char* kProtocol = "camera_server://";
+wpi::DenseMap<int, std::unique_ptr<SendableCameraWrapper>> wrappers;
+} // namespace
+
+SendableCameraWrapper& SendableCameraWrapper::Wrap(
+ const cs::VideoSource& source) {
+ return Wrap(source.GetHandle());
+}
+
+SendableCameraWrapper& SendableCameraWrapper::Wrap(CS_Source source) {
+ auto& wrapper = wrappers[static_cast<int>(source)];
+ if (!wrapper)
+ wrapper = std::make_unique<SendableCameraWrapper>(source, private_init{});
+ return *wrapper;
+}
+
+SendableCameraWrapper::SendableCameraWrapper(CS_Source source,
+ const private_init&)
+ : SendableBase(false), m_uri(kProtocol) {
+ CS_Status status = 0;
+ auto name = cs::GetSourceName(source, &status);
+ SetName(name);
+ m_uri += name;
+}
+
+void SendableCameraWrapper::InitSendable(SendableBuilder& builder) {
+ builder.AddStringProperty(".ShuffleboardURI", [this] { return m_uri; },
+ nullptr);
+}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/Shuffleboard.cpp b/wpilibc/src/main/native/cpp/shuffleboard/Shuffleboard.cpp
new file mode 100644
index 0000000..2d69847
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/Shuffleboard.cpp
@@ -0,0 +1,73 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/Shuffleboard.h"
+
+#include <networktables/NetworkTableInstance.h>
+
+#include "frc/shuffleboard/ShuffleboardTab.h"
+
+using namespace frc;
+
+void Shuffleboard::Update() { GetInstance().Update(); }
+
+ShuffleboardTab& Shuffleboard::GetTab(wpi::StringRef title) {
+ return GetInstance().GetTab(title);
+}
+
+void Shuffleboard::SelectTab(int index) { GetInstance().SelectTab(index); }
+
+void Shuffleboard::SelectTab(wpi::StringRef title) {
+ GetInstance().SelectTab(title);
+}
+
+void Shuffleboard::EnableActuatorWidgets() {
+ GetInstance().EnableActuatorWidgets();
+}
+
+void Shuffleboard::DisableActuatorWidgets() {
+ // Need to update to make sure the sendable builders are initialized
+ Update();
+ GetInstance().DisableActuatorWidgets();
+}
+
+void Shuffleboard::StartRecording() {
+ GetRecordingController().StartRecording();
+}
+
+void Shuffleboard::StopRecording() { GetRecordingController().StopRecording(); }
+
+void Shuffleboard::SetRecordingFileNameFormat(wpi::StringRef format) {
+ GetRecordingController().SetRecordingFileNameFormat(format);
+}
+
+void Shuffleboard::ClearRecordingFileNameFormat() {
+ GetRecordingController().ClearRecordingFileNameFormat();
+}
+
+void Shuffleboard::AddEventMarker(wpi::StringRef name,
+ wpi::StringRef description,
+ ShuffleboardEventImportance importance) {
+ GetRecordingController().AddEventMarker(name, description, importance);
+}
+
+void Shuffleboard::AddEventMarker(wpi::StringRef name,
+ ShuffleboardEventImportance importance) {
+ AddEventMarker(name, "", importance);
+}
+
+detail::ShuffleboardInstance& Shuffleboard::GetInstance() {
+ static detail::ShuffleboardInstance inst(
+ nt::NetworkTableInstance::GetDefault());
+ return inst;
+}
+
+detail::RecordingController& Shuffleboard::GetRecordingController() {
+ static detail::RecordingController inst(
+ nt::NetworkTableInstance::GetDefault());
+ return inst;
+}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp
new file mode 100644
index 0000000..7617333
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp
@@ -0,0 +1,76 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/ShuffleboardComponentBase.h"
+
+#include <wpi/SmallVector.h>
+
+using namespace frc;
+
+ShuffleboardComponentBase::ShuffleboardComponentBase(
+ ShuffleboardContainer& parent, const wpi::Twine& title,
+ const wpi::Twine& type)
+ : ShuffleboardValue(title), m_parent(parent) {
+ wpi::SmallVector<char, 16> storage;
+ m_type = type.toStringRef(storage);
+}
+
+void ShuffleboardComponentBase::SetType(const wpi::Twine& type) {
+ wpi::SmallVector<char, 16> storage;
+ m_type = type.toStringRef(storage);
+ m_metadataDirty = true;
+}
+
+void ShuffleboardComponentBase::BuildMetadata(
+ std::shared_ptr<nt::NetworkTable> metaTable) {
+ if (!m_metadataDirty) {
+ return;
+ }
+ // Component type
+ if (GetType() == "") {
+ metaTable->GetEntry("PreferredComponent").Delete();
+ } else {
+ metaTable->GetEntry("PreferredComponent").ForceSetString(GetType());
+ }
+
+ // Tile size
+ if (m_width <= 0 || m_height <= 0) {
+ metaTable->GetEntry("Size").Delete();
+ } else {
+ metaTable->GetEntry("Size").SetDoubleArray(
+ {static_cast<double>(m_width), static_cast<double>(m_height)});
+ }
+
+ // Tile position
+ if (m_column < 0 || m_row < 0) {
+ metaTable->GetEntry("Position").Delete();
+ } else {
+ metaTable->GetEntry("Position")
+ .SetDoubleArray(
+ {static_cast<double>(m_column), static_cast<double>(m_row)});
+ }
+
+ // Custom properties
+ if (GetProperties().size() > 0) {
+ auto propTable = metaTable->GetSubTable("Properties");
+ for (auto& entry : GetProperties()) {
+ propTable->GetEntry(entry.first()).SetValue(entry.second);
+ }
+ }
+ m_metadataDirty = false;
+}
+
+ShuffleboardContainer& ShuffleboardComponentBase::GetParent() {
+ return m_parent;
+}
+
+const std::string& ShuffleboardComponentBase::GetType() const { return m_type; }
+
+const wpi::StringMap<std::shared_ptr<nt::Value>>&
+ShuffleboardComponentBase::GetProperties() const {
+ return m_properties;
+}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp
new file mode 100644
index 0000000..4954cff
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp
@@ -0,0 +1,195 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/ShuffleboardContainer.h"
+
+#include <wpi/SmallVector.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/shuffleboard/ComplexWidget.h"
+#include "frc/shuffleboard/SendableCameraWrapper.h"
+#include "frc/shuffleboard/ShuffleboardComponent.h"
+#include "frc/shuffleboard/ShuffleboardLayout.h"
+#include "frc/shuffleboard/SimpleWidget.h"
+
+using namespace frc;
+
+ShuffleboardContainer::ShuffleboardContainer(const wpi::Twine& title)
+ : ShuffleboardValue(title) {}
+
+const std::vector<std::unique_ptr<ShuffleboardComponentBase>>&
+ShuffleboardContainer::GetComponents() const {
+ return m_components;
+}
+
+ShuffleboardLayout& ShuffleboardContainer::GetLayout(const wpi::Twine& title,
+ const LayoutType& type) {
+ return GetLayout(title, type.GetLayoutName());
+}
+
+ShuffleboardLayout& ShuffleboardContainer::GetLayout(const wpi::Twine& title,
+ const wpi::Twine& type) {
+ wpi::SmallVector<char, 16> storage;
+ auto titleRef = title.toStringRef(storage);
+ if (m_layouts.count(titleRef) == 0) {
+ auto layout = std::make_unique<ShuffleboardLayout>(*this, type, titleRef);
+ auto ptr = layout.get();
+ m_components.emplace_back(std::move(layout));
+ m_layouts.insert(std::make_pair(titleRef, ptr));
+ }
+ return *m_layouts[titleRef];
+}
+
+ShuffleboardLayout& ShuffleboardContainer::GetLayout(const wpi::Twine& title) {
+ wpi::SmallVector<char, 16> storage;
+ auto titleRef = title.toStringRef(storage);
+ if (m_layouts.count(titleRef) == 0) {
+ wpi_setWPIErrorWithContext(
+ InvalidParameter, "No layout with the given title has been defined");
+ }
+ return *m_layouts[titleRef];
+}
+
+ComplexWidget& ShuffleboardContainer::Add(const wpi::Twine& title,
+ Sendable& sendable) {
+ CheckTitle(title);
+ auto widget = std::make_unique<ComplexWidget>(*this, title, sendable);
+ auto ptr = widget.get();
+ m_components.emplace_back(std::move(widget));
+ return *ptr;
+}
+
+ComplexWidget& ShuffleboardContainer::Add(const wpi::Twine& title,
+ const cs::VideoSource& video) {
+ return Add(title, SendableCameraWrapper::Wrap(video));
+}
+
+ComplexWidget& ShuffleboardContainer::Add(Sendable& sendable) {
+ if (sendable.GetName().empty()) {
+ wpi::outs() << "Sendable must have a name\n";
+ }
+ return Add(sendable.GetName(), sendable);
+}
+
+ComplexWidget& ShuffleboardContainer::Add(const cs::VideoSource& video) {
+ return Add(SendableCameraWrapper::Wrap(video));
+}
+
+SimpleWidget& ShuffleboardContainer::Add(
+ const wpi::Twine& title, std::shared_ptr<nt::Value> defaultValue) {
+ CheckTitle(title);
+
+ auto widget = std::make_unique<SimpleWidget>(*this, title);
+ auto ptr = widget.get();
+ m_components.emplace_back(std::move(widget));
+ ptr->GetEntry().SetDefaultValue(defaultValue);
+ return *ptr;
+}
+
+SimpleWidget& ShuffleboardContainer::Add(const wpi::Twine& title,
+ bool defaultValue) {
+ return Add(title, nt::Value::MakeBoolean(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::Add(const wpi::Twine& title,
+ double defaultValue) {
+ return Add(title, nt::Value::MakeDouble(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::Add(const wpi::Twine& title,
+ int defaultValue) {
+ return Add(title, nt::Value::MakeDouble(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::Add(const wpi::Twine& title,
+ const wpi::Twine& defaultValue) {
+ return Add(title, nt::Value::MakeString(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::Add(const wpi::Twine& title,
+ const char* defaultValue) {
+ return Add(title, nt::Value::MakeString(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::Add(const wpi::Twine& title,
+ wpi::ArrayRef<bool> defaultValue) {
+ return Add(title, nt::Value::MakeBooleanArray(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::Add(const wpi::Twine& title,
+ wpi::ArrayRef<double> defaultValue) {
+ return Add(title, nt::Value::MakeDoubleArray(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::Add(
+ const wpi::Twine& title, wpi::ArrayRef<std::string> defaultValue) {
+ return Add(title, nt::Value::MakeStringArray(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::AddPersistent(
+ const wpi::Twine& title, std::shared_ptr<nt::Value> defaultValue) {
+ auto& widget = Add(title, defaultValue);
+ widget.GetEntry().SetPersistent();
+ return widget;
+}
+
+SimpleWidget& ShuffleboardContainer::AddPersistent(const wpi::Twine& title,
+ bool defaultValue) {
+ return AddPersistent(title, nt::Value::MakeBoolean(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::AddPersistent(const wpi::Twine& title,
+ double defaultValue) {
+ return AddPersistent(title, nt::Value::MakeDouble(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::AddPersistent(const wpi::Twine& title,
+ int defaultValue) {
+ return AddPersistent(title, nt::Value::MakeDouble(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::AddPersistent(
+ const wpi::Twine& title, const wpi::Twine& defaultValue) {
+ return AddPersistent(title, nt::Value::MakeString(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::AddPersistent(
+ const wpi::Twine& title, wpi::ArrayRef<bool> defaultValue) {
+ return AddPersistent(title, nt::Value::MakeBooleanArray(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::AddPersistent(
+ const wpi::Twine& title, wpi::ArrayRef<double> defaultValue) {
+ return AddPersistent(title, nt::Value::MakeDoubleArray(defaultValue));
+}
+
+SimpleWidget& ShuffleboardContainer::AddPersistent(
+ const wpi::Twine& title, wpi::ArrayRef<std::string> defaultValue) {
+ return AddPersistent(title, nt::Value::MakeStringArray(defaultValue));
+}
+
+void ShuffleboardContainer::EnableIfActuator() {
+ for (auto& component : GetComponents()) {
+ component->EnableIfActuator();
+ }
+}
+
+void ShuffleboardContainer::DisableIfActuator() {
+ for (auto& component : GetComponents()) {
+ component->DisableIfActuator();
+ }
+}
+
+void ShuffleboardContainer::CheckTitle(const wpi::Twine& title) {
+ wpi::SmallVector<char, 16> storage;
+ auto titleRef = title.toStringRef(storage);
+ if (m_usedTitles.count(titleRef) > 0) {
+ wpi::errs() << "Title is already in use: " << title << "\n";
+ return;
+ }
+ m_usedTitles.insert(titleRef);
+}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardInstance.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardInstance.cpp
new file mode 100644
index 0000000..39e5778
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardInstance.cpp
@@ -0,0 +1,82 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/ShuffleboardInstance.h"
+
+#include <networktables/NetworkTable.h>
+#include <networktables/NetworkTableInstance.h>
+#include <wpi/StringMap.h>
+
+#include "frc/shuffleboard/Shuffleboard.h"
+
+using namespace frc::detail;
+
+struct ShuffleboardInstance::Impl {
+ wpi::StringMap<ShuffleboardTab> tabs;
+
+ bool tabsChanged = false;
+ std::shared_ptr<nt::NetworkTable> rootTable;
+ std::shared_ptr<nt::NetworkTable> rootMetaTable;
+};
+
+ShuffleboardInstance::ShuffleboardInstance(nt::NetworkTableInstance ntInstance)
+ : m_impl(new Impl) {
+ m_impl->rootTable = ntInstance.GetTable(Shuffleboard::kBaseTableName);
+ m_impl->rootMetaTable = m_impl->rootTable->GetSubTable(".metadata");
+}
+
+ShuffleboardInstance::~ShuffleboardInstance() {}
+
+frc::ShuffleboardTab& ShuffleboardInstance::GetTab(wpi::StringRef title) {
+ if (m_impl->tabs.find(title) == m_impl->tabs.end()) {
+ m_impl->tabs.try_emplace(title, ShuffleboardTab(*this, title));
+ m_impl->tabsChanged = true;
+ }
+ return m_impl->tabs.find(title)->second;
+}
+
+void ShuffleboardInstance::Update() {
+ if (m_impl->tabsChanged) {
+ std::vector<std::string> tabTitles;
+ for (auto& entry : m_impl->tabs) {
+ tabTitles.emplace_back(entry.second.GetTitle());
+ }
+ m_impl->rootMetaTable->GetEntry("Tabs").ForceSetStringArray(tabTitles);
+ m_impl->tabsChanged = false;
+ }
+ for (auto& entry : m_impl->tabs) {
+ auto& tab = entry.second;
+ tab.BuildInto(m_impl->rootTable,
+ m_impl->rootMetaTable->GetSubTable(tab.GetTitle()));
+ }
+}
+
+void ShuffleboardInstance::EnableActuatorWidgets() {
+ for (auto& entry : m_impl->tabs) {
+ auto& tab = entry.second;
+ for (auto& component : tab.GetComponents()) {
+ component->EnableIfActuator();
+ }
+ }
+}
+
+void ShuffleboardInstance::DisableActuatorWidgets() {
+ for (auto& entry : m_impl->tabs) {
+ auto& tab = entry.second;
+ for (auto& component : tab.GetComponents()) {
+ component->DisableIfActuator();
+ }
+ }
+}
+
+void ShuffleboardInstance::SelectTab(int index) {
+ m_impl->rootMetaTable->GetEntry("Selected").ForceSetDouble(index);
+}
+
+void ShuffleboardInstance::SelectTab(wpi::StringRef title) {
+ m_impl->rootMetaTable->GetEntry("Selected").ForceSetString(title);
+}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardLayout.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardLayout.cpp
new file mode 100644
index 0000000..8418b77
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardLayout.cpp
@@ -0,0 +1,30 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/ShuffleboardLayout.h"
+
+using namespace frc;
+
+ShuffleboardLayout::ShuffleboardLayout(ShuffleboardContainer& parent,
+ const wpi::Twine& name,
+ const wpi::Twine& type)
+ : ShuffleboardValue(type),
+ ShuffleboardComponent(parent, type, name),
+ ShuffleboardContainer(name) {
+ m_isLayout = true;
+}
+
+void ShuffleboardLayout::BuildInto(
+ std::shared_ptr<nt::NetworkTable> parentTable,
+ std::shared_ptr<nt::NetworkTable> metaTable) {
+ BuildMetadata(metaTable);
+ auto table = parentTable->GetSubTable(GetTitle());
+ table->GetEntry(".type").SetString("ShuffleboardLayout");
+ for (auto& component : GetComponents()) {
+ component->BuildInto(table, metaTable->GetSubTable(component->GetTitle()));
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardTab.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardTab.cpp
new file mode 100644
index 0000000..7a8338e
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardTab.cpp
@@ -0,0 +1,25 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/ShuffleboardTab.h"
+
+using namespace frc;
+
+ShuffleboardTab::ShuffleboardTab(ShuffleboardRoot& root, wpi::StringRef title)
+ : ShuffleboardValue(title), ShuffleboardContainer(title), m_root(root) {}
+
+ShuffleboardRoot& ShuffleboardTab::GetRoot() { return m_root; }
+
+void ShuffleboardTab::BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
+ std::shared_ptr<nt::NetworkTable> metaTable) {
+ auto tabTable = parentTable->GetSubTable(GetTitle());
+ tabTable->GetEntry(".type").SetString("ShuffleboardTab");
+ for (auto& component : GetComponents()) {
+ component->BuildInto(tabTable,
+ metaTable->GetSubTable(component->GetTitle()));
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/SimpleWidget.cpp b/wpilibc/src/main/native/cpp/shuffleboard/SimpleWidget.cpp
new file mode 100644
index 0000000..89af25d
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/SimpleWidget.cpp
@@ -0,0 +1,44 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/SimpleWidget.h"
+
+#include "frc/shuffleboard/Shuffleboard.h"
+#include "frc/shuffleboard/ShuffleboardLayout.h"
+#include "frc/shuffleboard/ShuffleboardTab.h"
+
+using namespace frc;
+
+SimpleWidget::SimpleWidget(ShuffleboardContainer& parent,
+ const wpi::Twine& title)
+ : ShuffleboardValue(title), ShuffleboardWidget(parent, title), m_entry() {}
+
+nt::NetworkTableEntry SimpleWidget::GetEntry() {
+ if (!m_entry) {
+ ForceGenerate();
+ }
+ return m_entry;
+}
+
+void SimpleWidget::BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
+ std::shared_ptr<nt::NetworkTable> metaTable) {
+ BuildMetadata(metaTable);
+ if (!m_entry) {
+ m_entry = parentTable->GetEntry(GetTitle());
+ }
+}
+
+void SimpleWidget::ForceGenerate() {
+ ShuffleboardContainer* parent = &GetParent();
+
+ while (parent->m_isLayout) {
+ parent = &(static_cast<ShuffleboardLayout*>(parent)->GetParent());
+ }
+
+ auto& tab = *static_cast<ShuffleboardTab*>(parent);
+ tab.GetRoot().Update();
+}
diff --git a/wpilibc/src/main/native/cpp/shuffleboard/WidgetType.cpp b/wpilibc/src/main/native/cpp/shuffleboard/WidgetType.cpp
new file mode 100644
index 0000000..cb73d30
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/shuffleboard/WidgetType.cpp
@@ -0,0 +1,12 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/WidgetType.h"
+
+using namespace frc;
+
+wpi::StringRef WidgetType::GetWidgetName() const { return m_widgetName; }
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/NamedSendable.cpp b/wpilibc/src/main/native/cpp/smartdashboard/NamedSendable.cpp
new file mode 100644
index 0000000..61028b3
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/smartdashboard/NamedSendable.cpp
@@ -0,0 +1,18 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/smartdashboard/NamedSendable.h"
+
+using namespace frc;
+
+void NamedSendable::SetName(const wpi::Twine&) {}
+
+std::string NamedSendable::GetSubsystem() const { return std::string(); }
+
+void NamedSendable::SetSubsystem(const wpi::Twine&) {}
+
+void NamedSendable::InitSendable(SendableBuilder&) {}
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/SendableBase.cpp b/wpilibc/src/main/native/cpp/smartdashboard/SendableBase.cpp
new file mode 100644
index 0000000..28bd7fd
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/smartdashboard/SendableBase.cpp
@@ -0,0 +1,72 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/smartdashboard/SendableBase.h"
+
+#include <utility>
+
+#include "frc/livewindow/LiveWindow.h"
+
+using namespace frc;
+
+SendableBase::SendableBase(bool addLiveWindow) {
+ if (addLiveWindow) LiveWindow::GetInstance()->Add(this);
+}
+
+SendableBase::~SendableBase() { LiveWindow::GetInstance()->Remove(this); }
+
+SendableBase::SendableBase(SendableBase&& rhs) {
+ m_name = std::move(rhs.m_name);
+ m_subsystem = std::move(rhs.m_subsystem);
+}
+
+SendableBase& SendableBase::operator=(SendableBase&& rhs) {
+ Sendable::operator=(std::move(rhs));
+
+ m_name = std::move(rhs.m_name);
+ m_subsystem = std::move(rhs.m_subsystem);
+
+ return *this;
+}
+
+std::string SendableBase::GetName() const {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ return m_name;
+}
+
+void SendableBase::SetName(const wpi::Twine& name) {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ m_name = name.str();
+}
+
+std::string SendableBase::GetSubsystem() const {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ return m_subsystem;
+}
+
+void SendableBase::SetSubsystem(const wpi::Twine& subsystem) {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ m_subsystem = subsystem.str();
+}
+
+void SendableBase::AddChild(std::shared_ptr<Sendable> child) {
+ LiveWindow::GetInstance()->AddChild(this, child);
+}
+
+void SendableBase::AddChild(void* child) {
+ LiveWindow::GetInstance()->AddChild(this, child);
+}
+
+void SendableBase::SetName(const wpi::Twine& moduleType, int channel) {
+ SetName(moduleType + wpi::Twine('[') + wpi::Twine(channel) + wpi::Twine(']'));
+}
+
+void SendableBase::SetName(const wpi::Twine& moduleType, int moduleNumber,
+ int channel) {
+ SetName(moduleType + wpi::Twine('[') + wpi::Twine(moduleNumber) +
+ wpi::Twine(',') + wpi::Twine(channel) + wpi::Twine(']'));
+}
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/SendableBuilderImpl.cpp b/wpilibc/src/main/native/cpp/smartdashboard/SendableBuilderImpl.cpp
new file mode 100644
index 0000000..bce03b5
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/smartdashboard/SendableBuilderImpl.cpp
@@ -0,0 +1,382 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/smartdashboard/SendableBuilderImpl.h"
+
+#include <ntcore_cpp.h>
+#include <wpi/SmallString.h>
+
+using namespace frc;
+
+void SendableBuilderImpl::SetTable(std::shared_ptr<nt::NetworkTable> table) {
+ m_table = table;
+ m_controllableEntry = table->GetEntry(".controllable");
+}
+
+std::shared_ptr<nt::NetworkTable> SendableBuilderImpl::GetTable() {
+ return m_table;
+}
+
+bool SendableBuilderImpl::IsActuator() const { return m_actuator; }
+
+void SendableBuilderImpl::UpdateTable() {
+ uint64_t time = nt::Now();
+ for (auto& property : m_properties) {
+ if (property.update) property.update(property.entry, time);
+ }
+ if (m_updateTable) m_updateTable();
+}
+
+void SendableBuilderImpl::StartListeners() {
+ for (auto& property : m_properties) property.StartListener();
+ if (m_controllableEntry) m_controllableEntry.SetBoolean(true);
+}
+
+void SendableBuilderImpl::StopListeners() {
+ for (auto& property : m_properties) property.StopListener();
+ if (m_controllableEntry) m_controllableEntry.SetBoolean(false);
+}
+
+void SendableBuilderImpl::StartLiveWindowMode() {
+ if (m_safeState) m_safeState();
+ StartListeners();
+}
+
+void SendableBuilderImpl::StopLiveWindowMode() {
+ StopListeners();
+ if (m_safeState) m_safeState();
+}
+
+void SendableBuilderImpl::SetSmartDashboardType(const wpi::Twine& type) {
+ m_table->GetEntry(".type").SetString(type);
+}
+
+void SendableBuilderImpl::SetActuator(bool value) {
+ m_table->GetEntry(".actuator").SetBoolean(value);
+ m_actuator = value;
+}
+
+void SendableBuilderImpl::SetSafeState(std::function<void()> func) {
+ m_safeState = func;
+}
+
+void SendableBuilderImpl::SetUpdateTable(std::function<void()> func) {
+ m_updateTable = func;
+}
+
+nt::NetworkTableEntry SendableBuilderImpl::GetEntry(const wpi::Twine& key) {
+ return m_table->GetEntry(key);
+}
+
+void SendableBuilderImpl::AddBooleanProperty(const wpi::Twine& key,
+ std::function<bool()> getter,
+ std::function<void(bool)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ entry.SetValue(nt::Value::MakeBoolean(getter(), time));
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) {
+ if (!event.value->IsBoolean()) return;
+ setter(event.value->GetBoolean());
+ },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
+
+void SendableBuilderImpl::AddDoubleProperty(
+ const wpi::Twine& key, std::function<double()> getter,
+ std::function<void(double)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ entry.SetValue(nt::Value::MakeDouble(getter(), time));
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) {
+ if (!event.value->IsDouble()) return;
+ setter(event.value->GetDouble());
+ },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
+
+void SendableBuilderImpl::AddStringProperty(
+ const wpi::Twine& key, std::function<std::string()> getter,
+ std::function<void(wpi::StringRef)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ entry.SetValue(nt::Value::MakeString(getter(), time));
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) {
+ if (!event.value->IsString()) return;
+ setter(event.value->GetString());
+ },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
+
+void SendableBuilderImpl::AddBooleanArrayProperty(
+ const wpi::Twine& key, std::function<std::vector<int>()> getter,
+ std::function<void(wpi::ArrayRef<int>)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ entry.SetValue(nt::Value::MakeBooleanArray(getter(), time));
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) {
+ if (!event.value->IsBooleanArray()) return;
+ setter(event.value->GetBooleanArray());
+ },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
+
+void SendableBuilderImpl::AddDoubleArrayProperty(
+ const wpi::Twine& key, std::function<std::vector<double>()> getter,
+ std::function<void(wpi::ArrayRef<double>)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ entry.SetValue(nt::Value::MakeDoubleArray(getter(), time));
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) {
+ if (!event.value->IsDoubleArray()) return;
+ setter(event.value->GetDoubleArray());
+ },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
+
+void SendableBuilderImpl::AddStringArrayProperty(
+ const wpi::Twine& key, std::function<std::vector<std::string>()> getter,
+ std::function<void(wpi::ArrayRef<std::string>)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ entry.SetValue(nt::Value::MakeStringArray(getter(), time));
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) {
+ if (!event.value->IsStringArray()) return;
+ setter(event.value->GetStringArray());
+ },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
+
+void SendableBuilderImpl::AddRawProperty(
+ const wpi::Twine& key, std::function<std::string()> getter,
+ std::function<void(wpi::StringRef)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ entry.SetValue(nt::Value::MakeRaw(getter(), time));
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) {
+ if (!event.value->IsRaw()) return;
+ setter(event.value->GetRaw());
+ },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
+
+void SendableBuilderImpl::AddValueProperty(
+ const wpi::Twine& key, std::function<std::shared_ptr<nt::Value>()> getter,
+ std::function<void(std::shared_ptr<nt::Value>)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ entry.SetValue(getter());
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) { setter(event.value); },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
+
+void SendableBuilderImpl::AddSmallStringProperty(
+ const wpi::Twine& key,
+ std::function<wpi::StringRef(wpi::SmallVectorImpl<char>& buf)> getter,
+ std::function<void(wpi::StringRef)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ wpi::SmallString<128> buf;
+ entry.SetValue(nt::Value::MakeString(getter(buf), time));
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) {
+ if (!event.value->IsString()) return;
+ setter(event.value->GetString());
+ },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
+
+void SendableBuilderImpl::AddSmallBooleanArrayProperty(
+ const wpi::Twine& key,
+ std::function<wpi::ArrayRef<int>(wpi::SmallVectorImpl<int>& buf)> getter,
+ std::function<void(wpi::ArrayRef<int>)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ wpi::SmallVector<int, 16> buf;
+ entry.SetValue(nt::Value::MakeBooleanArray(getter(buf), time));
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) {
+ if (!event.value->IsBooleanArray()) return;
+ setter(event.value->GetBooleanArray());
+ },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
+
+void SendableBuilderImpl::AddSmallDoubleArrayProperty(
+ const wpi::Twine& key,
+ std::function<wpi::ArrayRef<double>(wpi::SmallVectorImpl<double>& buf)>
+ getter,
+ std::function<void(wpi::ArrayRef<double>)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ wpi::SmallVector<double, 16> buf;
+ entry.SetValue(nt::Value::MakeDoubleArray(getter(buf), time));
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) {
+ if (!event.value->IsDoubleArray()) return;
+ setter(event.value->GetDoubleArray());
+ },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
+
+void SendableBuilderImpl::AddSmallStringArrayProperty(
+ const wpi::Twine& key,
+ std::function<
+ wpi::ArrayRef<std::string>(wpi::SmallVectorImpl<std::string>& buf)>
+ getter,
+ std::function<void(wpi::ArrayRef<std::string>)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ wpi::SmallVector<std::string, 16> buf;
+ entry.SetValue(nt::Value::MakeStringArray(getter(buf), time));
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) {
+ if (!event.value->IsStringArray()) return;
+ setter(event.value->GetStringArray());
+ },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
+
+void SendableBuilderImpl::AddSmallRawProperty(
+ const wpi::Twine& key,
+ std::function<wpi::StringRef(wpi::SmallVectorImpl<char>& buf)> getter,
+ std::function<void(wpi::StringRef)> setter) {
+ m_properties.emplace_back(*m_table, key);
+ if (getter) {
+ m_properties.back().update = [=](nt::NetworkTableEntry entry,
+ uint64_t time) {
+ wpi::SmallVector<char, 128> buf;
+ entry.SetValue(nt::Value::MakeRaw(getter(buf), time));
+ };
+ }
+ if (setter) {
+ m_properties.back().createListener =
+ [=](nt::NetworkTableEntry entry) -> NT_EntryListener {
+ return entry.AddListener(
+ [=](const nt::EntryNotification& event) {
+ if (!event.value->IsRaw()) return;
+ setter(event.value->GetRaw());
+ },
+ NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
+ };
+ }
+}
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/SendableChooserBase.cpp b/wpilibc/src/main/native/cpp/smartdashboard/SendableChooserBase.cpp
new file mode 100644
index 0000000..2cdf92c
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/smartdashboard/SendableChooserBase.cpp
@@ -0,0 +1,15 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/smartdashboard/SendableChooserBase.h"
+
+using namespace frc;
+
+std::atomic_int SendableChooserBase::s_instances{0};
+
+SendableChooserBase::SendableChooserBase()
+ : SendableBase(false), m_instance{s_instances++} {}
diff --git a/wpilibc/src/main/native/cpp/smartdashboard/SmartDashboard.cpp b/wpilibc/src/main/native/cpp/smartdashboard/SmartDashboard.cpp
new file mode 100644
index 0000000..98e5568
--- /dev/null
+++ b/wpilibc/src/main/native/cpp/smartdashboard/SmartDashboard.cpp
@@ -0,0 +1,263 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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 "frc/smartdashboard/SmartDashboard.h"
+
+#include <hal/HAL.h>
+#include <networktables/NetworkTable.h>
+#include <networktables/NetworkTableInstance.h>
+#include <wpi/StringMap.h>
+#include <wpi/mutex.h>
+
+#include "frc/WPIErrors.h"
+#include "frc/smartdashboard/Sendable.h"
+#include "frc/smartdashboard/SendableBuilderImpl.h"
+
+using namespace frc;
+
+namespace {
+class SmartDashboardData {
+ public:
+ SmartDashboardData() = default;
+ explicit SmartDashboardData(Sendable* sendable_) : sendable(sendable_) {}
+
+ Sendable* sendable = nullptr;
+ SendableBuilderImpl builder;
+};
+
+class Singleton {
+ public:
+ static Singleton& GetInstance();
+
+ std::shared_ptr<nt::NetworkTable> table;
+ wpi::StringMap<SmartDashboardData> tablesToData;
+ wpi::mutex tablesToDataMutex;
+
+ private:
+ Singleton() {
+ table = nt::NetworkTableInstance::GetDefault().GetTable("SmartDashboard");
+ HAL_Report(HALUsageReporting::kResourceType_SmartDashboard, 0);
+ }
+ Singleton(const Singleton&) = delete;
+ Singleton& operator=(const Singleton&) = delete;
+};
+
+} // namespace
+
+Singleton& Singleton::GetInstance() {
+ static Singleton instance;
+ return instance;
+}
+
+void SmartDashboard::init() { Singleton::GetInstance(); }
+
+bool SmartDashboard::ContainsKey(wpi::StringRef key) {
+ return Singleton::GetInstance().table->ContainsKey(key);
+}
+
+std::vector<std::string> SmartDashboard::GetKeys(int types) {
+ return Singleton::GetInstance().table->GetKeys(types);
+}
+
+void SmartDashboard::SetPersistent(wpi::StringRef key) {
+ Singleton::GetInstance().table->GetEntry(key).SetPersistent();
+}
+
+void SmartDashboard::ClearPersistent(wpi::StringRef key) {
+ Singleton::GetInstance().table->GetEntry(key).ClearPersistent();
+}
+
+bool SmartDashboard::IsPersistent(wpi::StringRef key) {
+ return Singleton::GetInstance().table->GetEntry(key).IsPersistent();
+}
+
+void SmartDashboard::SetFlags(wpi::StringRef key, unsigned int flags) {
+ Singleton::GetInstance().table->GetEntry(key).SetFlags(flags);
+}
+
+void SmartDashboard::ClearFlags(wpi::StringRef key, unsigned int flags) {
+ Singleton::GetInstance().table->GetEntry(key).ClearFlags(flags);
+}
+
+unsigned int SmartDashboard::GetFlags(wpi::StringRef key) {
+ return Singleton::GetInstance().table->GetEntry(key).GetFlags();
+}
+
+void SmartDashboard::Delete(wpi::StringRef key) {
+ Singleton::GetInstance().table->Delete(key);
+}
+
+void SmartDashboard::PutData(wpi::StringRef key, Sendable* data) {
+ if (data == nullptr) {
+ wpi_setGlobalWPIErrorWithContext(NullParameter, "value");
+ return;
+ }
+ auto& inst = Singleton::GetInstance();
+ std::lock_guard<wpi::mutex> lock(inst.tablesToDataMutex);
+ auto& sddata = inst.tablesToData[key];
+ if (!sddata.sendable || sddata.sendable != data) {
+ sddata = SmartDashboardData(data);
+ auto dataTable = inst.table->GetSubTable(key);
+ sddata.builder.SetTable(dataTable);
+ data->InitSendable(sddata.builder);
+ sddata.builder.UpdateTable();
+ sddata.builder.StartListeners();
+ dataTable->GetEntry(".name").SetString(key);
+ }
+}
+
+void SmartDashboard::PutData(Sendable* value) {
+ if (value == nullptr) {
+ wpi_setGlobalWPIErrorWithContext(NullParameter, "value");
+ return;
+ }
+ PutData(value->GetName(), value);
+}
+
+Sendable* SmartDashboard::GetData(wpi::StringRef key) {
+ auto& inst = Singleton::GetInstance();
+ std::lock_guard<wpi::mutex> lock(inst.tablesToDataMutex);
+ auto data = inst.tablesToData.find(key);
+ if (data == inst.tablesToData.end()) {
+ wpi_setGlobalWPIErrorWithContext(SmartDashboardMissingKey, key);
+ return nullptr;
+ }
+ return data->getValue().sendable;
+}
+
+bool SmartDashboard::PutBoolean(wpi::StringRef keyName, bool value) {
+ return Singleton::GetInstance().table->GetEntry(keyName).SetBoolean(value);
+}
+
+bool SmartDashboard::SetDefaultBoolean(wpi::StringRef key, bool defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(key).SetDefaultBoolean(
+ defaultValue);
+}
+
+bool SmartDashboard::GetBoolean(wpi::StringRef keyName, bool defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(keyName).GetBoolean(
+ defaultValue);
+}
+
+bool SmartDashboard::PutNumber(wpi::StringRef keyName, double value) {
+ return Singleton::GetInstance().table->GetEntry(keyName).SetDouble(value);
+}
+
+bool SmartDashboard::SetDefaultNumber(wpi::StringRef key, double defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(key).SetDefaultDouble(
+ defaultValue);
+}
+
+double SmartDashboard::GetNumber(wpi::StringRef keyName, double defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(keyName).GetDouble(
+ defaultValue);
+}
+
+bool SmartDashboard::PutString(wpi::StringRef keyName, wpi::StringRef value) {
+ return Singleton::GetInstance().table->GetEntry(keyName).SetString(value);
+}
+
+bool SmartDashboard::SetDefaultString(wpi::StringRef key,
+ wpi::StringRef defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(key).SetDefaultString(
+ defaultValue);
+}
+
+std::string SmartDashboard::GetString(wpi::StringRef keyName,
+ wpi::StringRef defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(keyName).GetString(
+ defaultValue);
+}
+
+bool SmartDashboard::PutBooleanArray(wpi::StringRef key,
+ wpi::ArrayRef<int> value) {
+ return Singleton::GetInstance().table->GetEntry(key).SetBooleanArray(value);
+}
+
+bool SmartDashboard::SetDefaultBooleanArray(wpi::StringRef key,
+ wpi::ArrayRef<int> defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(key).SetDefaultBooleanArray(
+ defaultValue);
+}
+
+std::vector<int> SmartDashboard::GetBooleanArray(
+ wpi::StringRef key, wpi::ArrayRef<int> defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(key).GetBooleanArray(
+ defaultValue);
+}
+
+bool SmartDashboard::PutNumberArray(wpi::StringRef key,
+ wpi::ArrayRef<double> value) {
+ return Singleton::GetInstance().table->GetEntry(key).SetDoubleArray(value);
+}
+
+bool SmartDashboard::SetDefaultNumberArray(wpi::StringRef key,
+ wpi::ArrayRef<double> defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(key).SetDefaultDoubleArray(
+ defaultValue);
+}
+
+std::vector<double> SmartDashboard::GetNumberArray(
+ wpi::StringRef key, wpi::ArrayRef<double> defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(key).GetDoubleArray(
+ defaultValue);
+}
+
+bool SmartDashboard::PutStringArray(wpi::StringRef key,
+ wpi::ArrayRef<std::string> value) {
+ return Singleton::GetInstance().table->GetEntry(key).SetStringArray(value);
+}
+
+bool SmartDashboard::SetDefaultStringArray(
+ wpi::StringRef key, wpi::ArrayRef<std::string> defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(key).SetDefaultStringArray(
+ defaultValue);
+}
+
+std::vector<std::string> SmartDashboard::GetStringArray(
+ wpi::StringRef key, wpi::ArrayRef<std::string> defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(key).GetStringArray(
+ defaultValue);
+}
+
+bool SmartDashboard::PutRaw(wpi::StringRef key, wpi::StringRef value) {
+ return Singleton::GetInstance().table->GetEntry(key).SetRaw(value);
+}
+
+bool SmartDashboard::SetDefaultRaw(wpi::StringRef key,
+ wpi::StringRef defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(key).SetDefaultRaw(
+ defaultValue);
+}
+
+std::string SmartDashboard::GetRaw(wpi::StringRef key,
+ wpi::StringRef defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(key).GetRaw(defaultValue);
+}
+
+bool SmartDashboard::PutValue(wpi::StringRef keyName,
+ std::shared_ptr<nt::Value> value) {
+ return Singleton::GetInstance().table->GetEntry(keyName).SetValue(value);
+}
+
+bool SmartDashboard::SetDefaultValue(wpi::StringRef key,
+ std::shared_ptr<nt::Value> defaultValue) {
+ return Singleton::GetInstance().table->GetEntry(key).SetDefaultValue(
+ defaultValue);
+}
+
+std::shared_ptr<nt::Value> SmartDashboard::GetValue(wpi::StringRef keyName) {
+ return Singleton::GetInstance().table->GetEntry(keyName).GetValue();
+}
+
+void SmartDashboard::UpdateValues() {
+ auto& inst = Singleton::GetInstance();
+ std::lock_guard<wpi::mutex> lock(inst.tablesToDataMutex);
+ for (auto& i : inst.tablesToData) {
+ i.getValue().builder.UpdateTable();
+ }
+}
diff --git a/wpilibc/src/main/native/include/ADXL345_I2C.h b/wpilibc/src/main/native/include/ADXL345_I2C.h
new file mode 100644
index 0000000..a155d6c0
--- /dev/null
+++ b/wpilibc/src/main/native/include/ADXL345_I2C.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: ADXL345_I2C.h is deprecated; include frc/ADXL345_I2C.h instead"
+#else
+#warning "ADXL345_I2C.h is deprecated; include frc/ADXL345_I2C.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/ADXL345_I2C.h"
diff --git a/wpilibc/src/main/native/include/ADXL345_SPI.h b/wpilibc/src/main/native/include/ADXL345_SPI.h
new file mode 100644
index 0000000..490594c
--- /dev/null
+++ b/wpilibc/src/main/native/include/ADXL345_SPI.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: ADXL345_SPI.h is deprecated; include frc/ADXL345_SPI.h instead"
+#else
+#warning "ADXL345_SPI.h is deprecated; include frc/ADXL345_SPI.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/ADXL345_SPI.h"
diff --git a/wpilibc/src/main/native/include/ADXL362.h b/wpilibc/src/main/native/include/ADXL362.h
new file mode 100644
index 0000000..238ee10
--- /dev/null
+++ b/wpilibc/src/main/native/include/ADXL362.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: ADXL362.h is deprecated; include frc/ADXL362.h instead"
+#else
+#warning "ADXL362.h is deprecated; include frc/ADXL362.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/ADXL362.h"
diff --git a/wpilibc/src/main/native/include/ADXRS450_Gyro.h b/wpilibc/src/main/native/include/ADXRS450_Gyro.h
new file mode 100644
index 0000000..46b337f
--- /dev/null
+++ b/wpilibc/src/main/native/include/ADXRS450_Gyro.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: ADXRS450_Gyro.h is deprecated; include frc/ADXRS450_Gyro.h instead"
+#else
+#warning "ADXRS450_Gyro.h is deprecated; include frc/ADXRS450_Gyro.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/ADXRS450_Gyro.h"
diff --git a/wpilibc/src/main/native/include/AnalogAccelerometer.h b/wpilibc/src/main/native/include/AnalogAccelerometer.h
new file mode 100644
index 0000000..926005e
--- /dev/null
+++ b/wpilibc/src/main/native/include/AnalogAccelerometer.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: AnalogAccelerometer.h is deprecated; include frc/AnalogAccelerometer.h instead"
+#else
+#warning "AnalogAccelerometer.h is deprecated; include frc/AnalogAccelerometer.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/AnalogAccelerometer.h"
diff --git a/wpilibc/src/main/native/include/AnalogGyro.h b/wpilibc/src/main/native/include/AnalogGyro.h
new file mode 100644
index 0000000..287bf46
--- /dev/null
+++ b/wpilibc/src/main/native/include/AnalogGyro.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: AnalogGyro.h is deprecated; include frc/AnalogGyro.h instead"
+#else
+#warning "AnalogGyro.h is deprecated; include frc/AnalogGyro.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/AnalogGyro.h"
diff --git a/wpilibc/src/main/native/include/AnalogInput.h b/wpilibc/src/main/native/include/AnalogInput.h
new file mode 100644
index 0000000..64bacdf
--- /dev/null
+++ b/wpilibc/src/main/native/include/AnalogInput.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: AnalogInput.h is deprecated; include frc/AnalogInput.h instead"
+#else
+#warning "AnalogInput.h is deprecated; include frc/AnalogInput.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/AnalogInput.h"
diff --git a/wpilibc/src/main/native/include/AnalogOutput.h b/wpilibc/src/main/native/include/AnalogOutput.h
new file mode 100644
index 0000000..b08d3ee
--- /dev/null
+++ b/wpilibc/src/main/native/include/AnalogOutput.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: AnalogOutput.h is deprecated; include frc/AnalogOutput.h instead"
+#else
+#warning "AnalogOutput.h is deprecated; include frc/AnalogOutput.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/AnalogOutput.h"
diff --git a/wpilibc/src/main/native/include/AnalogPotentiometer.h b/wpilibc/src/main/native/include/AnalogPotentiometer.h
new file mode 100644
index 0000000..5b01b97
--- /dev/null
+++ b/wpilibc/src/main/native/include/AnalogPotentiometer.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: AnalogPotentiometer.h is deprecated; include frc/AnalogPotentiometer.h instead"
+#else
+#warning "AnalogPotentiometer.h is deprecated; include frc/AnalogPotentiometer.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/AnalogPotentiometer.h"
diff --git a/wpilibc/src/main/native/include/AnalogTrigger.h b/wpilibc/src/main/native/include/AnalogTrigger.h
new file mode 100644
index 0000000..e88547d
--- /dev/null
+++ b/wpilibc/src/main/native/include/AnalogTrigger.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: AnalogTrigger.h is deprecated; include frc/AnalogTrigger.h instead"
+#else
+#warning "AnalogTrigger.h is deprecated; include frc/AnalogTrigger.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/AnalogTrigger.h"
diff --git a/wpilibc/src/main/native/include/AnalogTriggerOutput.h b/wpilibc/src/main/native/include/AnalogTriggerOutput.h
new file mode 100644
index 0000000..d8754a0
--- /dev/null
+++ b/wpilibc/src/main/native/include/AnalogTriggerOutput.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: AnalogTriggerOutput.h is deprecated; include frc/AnalogTriggerOutput.h instead"
+#else
+#warning "AnalogTriggerOutput.h is deprecated; include frc/AnalogTriggerOutput.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/AnalogTriggerOutput.h"
diff --git a/wpilibc/src/main/native/include/AnalogTriggerType.h b/wpilibc/src/main/native/include/AnalogTriggerType.h
new file mode 100644
index 0000000..6f55772
--- /dev/null
+++ b/wpilibc/src/main/native/include/AnalogTriggerType.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: AnalogTriggerType.h is deprecated; include frc/AnalogTriggerType.h instead"
+#else
+#warning "AnalogTriggerType.h is deprecated; include frc/AnalogTriggerType.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/AnalogTriggerType.h"
diff --git a/wpilibc/src/main/native/include/Base.h b/wpilibc/src/main/native/include/Base.h
new file mode 100644
index 0000000..c6fc91a
--- /dev/null
+++ b/wpilibc/src/main/native/include/Base.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Base.h is deprecated; include frc/Base.h instead"
+#else
+#warning "Base.h is deprecated; include frc/Base.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Base.h"
diff --git a/wpilibc/src/main/native/include/BuiltInAccelerometer.h b/wpilibc/src/main/native/include/BuiltInAccelerometer.h
new file mode 100644
index 0000000..e394037
--- /dev/null
+++ b/wpilibc/src/main/native/include/BuiltInAccelerometer.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: BuiltInAccelerometer.h is deprecated; include frc/BuiltInAccelerometer.h instead"
+#else
+#warning "BuiltInAccelerometer.h is deprecated; include frc/BuiltInAccelerometer.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/BuiltInAccelerometer.h"
diff --git a/wpilibc/src/main/native/include/Buttons/Button.h b/wpilibc/src/main/native/include/Buttons/Button.h
new file mode 100644
index 0000000..f71bee2
--- /dev/null
+++ b/wpilibc/src/main/native/include/Buttons/Button.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Buttons/Button.h is deprecated; include frc/buttons/Button.h instead"
+#else
+#warning "Buttons/Button.h is deprecated; include frc/buttons/Button.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/buttons/Button.h"
diff --git a/wpilibc/src/main/native/include/Buttons/ButtonScheduler.h b/wpilibc/src/main/native/include/Buttons/ButtonScheduler.h
new file mode 100644
index 0000000..48392c7
--- /dev/null
+++ b/wpilibc/src/main/native/include/Buttons/ButtonScheduler.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: buttons/ButtonScheduler.h is deprecated; include frc/buttons/ButtonScheduler.h instead"
+#else
+#warning "buttons/ButtonScheduler.h is deprecated; include frc/buttons/ButtonScheduler.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/buttons/ButtonScheduler.h"
diff --git a/wpilibc/src/main/native/include/Buttons/CancelButtonScheduler.h b/wpilibc/src/main/native/include/Buttons/CancelButtonScheduler.h
new file mode 100644
index 0000000..201d024
--- /dev/null
+++ b/wpilibc/src/main/native/include/Buttons/CancelButtonScheduler.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: buttons/CancelButtonScheduler.h is deprecated; include frc/buttons/CancelButtonScheduler.h instead"
+#else
+#warning "buttons/CancelButtonScheduler.h is deprecated; include frc/buttons/CancelButtonScheduler.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/buttons/CancelButtonScheduler.h"
diff --git a/wpilibc/src/main/native/include/Buttons/HeldButtonScheduler.h b/wpilibc/src/main/native/include/Buttons/HeldButtonScheduler.h
new file mode 100644
index 0000000..4886832
--- /dev/null
+++ b/wpilibc/src/main/native/include/Buttons/HeldButtonScheduler.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: buttons/HeldButtonScheduler.h is deprecated; include frc/buttons/HeldButtonScheduler.h instead"
+#else
+#warning "buttons/HeldButtonScheduler.h is deprecated; include frc/buttons/HeldButtonScheduler.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/buttons/HeldButtonScheduler.h"
diff --git a/wpilibc/src/main/native/include/Buttons/InternalButton.h b/wpilibc/src/main/native/include/Buttons/InternalButton.h
new file mode 100644
index 0000000..4cde15a
--- /dev/null
+++ b/wpilibc/src/main/native/include/Buttons/InternalButton.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: buttons/InternalButton.h is deprecated; include frc/buttons/InternalButton.h instead"
+#else
+#warning "buttons/InternalButton.h is deprecated; include frc/buttons/InternalButton.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/buttons/InternalButton.h"
diff --git a/wpilibc/src/main/native/include/Buttons/JoystickButton.h b/wpilibc/src/main/native/include/Buttons/JoystickButton.h
new file mode 100644
index 0000000..6ad611e
--- /dev/null
+++ b/wpilibc/src/main/native/include/Buttons/JoystickButton.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: buttons/JoystickButton.h is deprecated; include frc/buttons/JoystickButton.h instead"
+#else
+#warning "buttons/JoystickButton.h is deprecated; include frc/buttons/JoystickButton.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/buttons/JoystickButton.h"
diff --git a/wpilibc/src/main/native/include/Buttons/NetworkButton.h b/wpilibc/src/main/native/include/Buttons/NetworkButton.h
new file mode 100644
index 0000000..8d23810
--- /dev/null
+++ b/wpilibc/src/main/native/include/Buttons/NetworkButton.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: buttons/NetworkButton.h is deprecated; include frc/buttons/NetworkButton.h instead"
+#else
+#warning "buttons/NetworkButton.h is deprecated; include frc/buttons/NetworkButton.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/buttons/NetworkButton.h"
diff --git a/wpilibc/src/main/native/include/Buttons/PressedButtonScheduler.h b/wpilibc/src/main/native/include/Buttons/PressedButtonScheduler.h
new file mode 100644
index 0000000..323d9e2
--- /dev/null
+++ b/wpilibc/src/main/native/include/Buttons/PressedButtonScheduler.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: buttons/PressedButtonScheduler.h is deprecated; include frc/buttons/PressedButtonScheduler.h instead"
+#else
+#warning "buttons/PressedButtonScheduler.h is deprecated; include frc/buttons/PressedButtonScheduler.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/buttons/PressedButtonScheduler.h"
diff --git a/wpilibc/src/main/native/include/Buttons/ReleasedButtonScheduler.h b/wpilibc/src/main/native/include/Buttons/ReleasedButtonScheduler.h
new file mode 100644
index 0000000..88ef25c
--- /dev/null
+++ b/wpilibc/src/main/native/include/Buttons/ReleasedButtonScheduler.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: buttons/ReleasedButtonScheduler.h is deprecated; include frc/buttons/ReleasedButtonScheduler.h instead"
+#else
+#warning "buttons/ReleasedButtonScheduler.h is deprecated; include frc/buttons/ReleasedButtonScheduler.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/buttons/ReleasedButtonScheduler.h"
diff --git a/wpilibc/src/main/native/include/Buttons/ToggleButtonScheduler.h b/wpilibc/src/main/native/include/Buttons/ToggleButtonScheduler.h
new file mode 100644
index 0000000..7848f91
--- /dev/null
+++ b/wpilibc/src/main/native/include/Buttons/ToggleButtonScheduler.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: buttons/ToggleButtonScheduler.h is deprecated; include frc/buttons/ToggleButtonScheduler.h instead"
+#else
+#warning "buttons/ToggleButtonScheduler.h is deprecated; include frc/buttons/ToggleButtonScheduler.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/buttons/ToggleButtonScheduler.h"
diff --git a/wpilibc/src/main/native/include/Buttons/Trigger.h b/wpilibc/src/main/native/include/Buttons/Trigger.h
new file mode 100644
index 0000000..7fb8889
--- /dev/null
+++ b/wpilibc/src/main/native/include/Buttons/Trigger.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: buttons/Trigger.h is deprecated; include frc/buttons/Trigger.h instead"
+#else
+#warning "buttons/Trigger.h is deprecated; include frc/buttons/Trigger.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/buttons/Trigger.h"
diff --git a/wpilibc/src/main/native/include/CAN.h b/wpilibc/src/main/native/include/CAN.h
new file mode 100644
index 0000000..28d49b8
--- /dev/null
+++ b/wpilibc/src/main/native/include/CAN.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: CAN.h is deprecated; include frc/CAN.h instead"
+#else
+#warning "CAN.h is deprecated; include frc/CAN.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/CAN.h"
diff --git a/wpilibc/src/main/native/include/Commands/Command.h b/wpilibc/src/main/native/include/Commands/Command.h
new file mode 100644
index 0000000..f170ced
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/Command.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/Command.h is deprecated; include frc/commands/Command.h instead"
+#else
+#warning "Commands/Command.h is deprecated; include frc/commands/Command.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/Command.h"
diff --git a/wpilibc/src/main/native/include/Commands/CommandGroup.h b/wpilibc/src/main/native/include/Commands/CommandGroup.h
new file mode 100644
index 0000000..0e124f2
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/CommandGroup.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/CommandGroup.h is deprecated; include frc/commands/CommandGroup.h instead"
+#else
+#warning "Commands/CommandGroup.h is deprecated; include frc/commands/CommandGroup.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/CommandGroup.h"
diff --git a/wpilibc/src/main/native/include/Commands/CommandGroupEntry.h b/wpilibc/src/main/native/include/Commands/CommandGroupEntry.h
new file mode 100644
index 0000000..1f5ee67
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/CommandGroupEntry.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/CommandGroupEntry.h is deprecated; include frc/commands/CommandGroupEntry.h instead"
+#else
+#warning "Commands/CommandGroupEntry.h is deprecated; include frc/commands/CommandGroupEntry.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/CommandGroupEntry.h"
diff --git a/wpilibc/src/main/native/include/Commands/ConditionalCommand.h b/wpilibc/src/main/native/include/Commands/ConditionalCommand.h
new file mode 100644
index 0000000..a0d3df8
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/ConditionalCommand.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/ConditionalCommand.h is deprecated; include frc/commands/ConditionalCommand.h instead"
+#else
+#warning "Commands/ConditionalCommand.h is deprecated; include frc/commands/ConditionalCommand.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/ConditionalCommand.h"
diff --git a/wpilibc/src/main/native/include/Commands/InstantCommand.h b/wpilibc/src/main/native/include/Commands/InstantCommand.h
new file mode 100644
index 0000000..c097c1a
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/InstantCommand.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/InstantCommand.h is deprecated; include frc/commands/InstantCommand.h instead"
+#else
+#warning "Commands/InstantCommand.h is deprecated; include frc/commands/InstantCommand.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/InstantCommand.h"
diff --git a/wpilibc/src/main/native/include/Commands/PIDCommand.h b/wpilibc/src/main/native/include/Commands/PIDCommand.h
new file mode 100644
index 0000000..462e807
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/PIDCommand.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/PIDCommand.h is deprecated; include frc/commands/PIDCommand.h instead"
+#else
+#warning "Commands/PIDCommand.h is deprecated; include frc/commands/PIDCommand.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/PIDCommand.h"
diff --git a/wpilibc/src/main/native/include/Commands/PIDSubsystem.h b/wpilibc/src/main/native/include/Commands/PIDSubsystem.h
new file mode 100644
index 0000000..d4bc1ee
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/PIDSubsystem.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/PIDSubsystem.h is deprecated; include frc/commands/PIDSubsystem.h instead"
+#else
+#warning "Commands/PIDSubsystem.h is deprecated; include frc/commands/PIDSubsystem.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/PIDSubsystem.h"
diff --git a/wpilibc/src/main/native/include/Commands/PrintCommand.h b/wpilibc/src/main/native/include/Commands/PrintCommand.h
new file mode 100644
index 0000000..801a539
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/PrintCommand.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/PrintCommand.h is deprecated; include frc/commands/PrintCommand.h instead"
+#else
+#warning "Commands/PrintCommand.h is deprecated; include frc/commands/PrintCommand.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/PrintCommand.h"
diff --git a/wpilibc/src/main/native/include/Commands/Scheduler.h b/wpilibc/src/main/native/include/Commands/Scheduler.h
new file mode 100644
index 0000000..df7591c
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/Scheduler.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/Scheduler.h is deprecated; include frc/commands/Scheduler.h instead"
+#else
+#warning "Commands/Scheduler.h is deprecated; include frc/commands/Scheduler.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/Scheduler.h"
diff --git a/wpilibc/src/main/native/include/Commands/StartCommand.h b/wpilibc/src/main/native/include/Commands/StartCommand.h
new file mode 100644
index 0000000..7ae1603
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/StartCommand.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/StartCommand.h is deprecated; include frc/commands/StartCommand.h instead"
+#else
+#warning "Commands/StartCommand.h is deprecated; include frc/commands/StartCommand.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/StartCommand.h"
diff --git a/wpilibc/src/main/native/include/Commands/Subsystem.h b/wpilibc/src/main/native/include/Commands/Subsystem.h
new file mode 100644
index 0000000..ffd0697
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/Subsystem.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/Subsystem.h is deprecated; include frc/commands/Subsystem.h instead"
+#else
+#warning "Commands/Subsystem.h is deprecated; include frc/commands/Subsystem.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/Subsystem.h"
diff --git a/wpilibc/src/main/native/include/Commands/TimedCommand.h b/wpilibc/src/main/native/include/Commands/TimedCommand.h
new file mode 100644
index 0000000..848f4b6
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/TimedCommand.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/TimedCommand.h is deprecated; include frc/commands/TimedCommand.h instead"
+#else
+#warning "Commands/TimedCommand.h is deprecated; include frc/commands/TimedCommand.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/TimedCommand.h"
diff --git a/wpilibc/src/main/native/include/Commands/WaitCommand.h b/wpilibc/src/main/native/include/Commands/WaitCommand.h
new file mode 100644
index 0000000..1901fba
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/WaitCommand.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/WaitCommand.h is deprecated; include frc/commands/WaitCommand.h instead"
+#else
+#warning "Commands/WaitCommand.h is deprecated; include frc/commands/WaitCommand.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/WaitCommand.h"
diff --git a/wpilibc/src/main/native/include/Commands/WaitForChildren.h b/wpilibc/src/main/native/include/Commands/WaitForChildren.h
new file mode 100644
index 0000000..178c835
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/WaitForChildren.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/WaitForChildren.h is deprecated; include frc/commands/WaitForChildren.h instead"
+#else
+#warning "Commands/WaitForChildren.h is deprecated; include frc/commands/WaitForChildren.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/WaitForChildren.h"
diff --git a/wpilibc/src/main/native/include/Commands/WaitUntilCommand.h b/wpilibc/src/main/native/include/Commands/WaitUntilCommand.h
new file mode 100644
index 0000000..b338d5f
--- /dev/null
+++ b/wpilibc/src/main/native/include/Commands/WaitUntilCommand.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Commands/WaitUntilCommand.h is deprecated; include frc/commands/WaitUntilCommand.h instead"
+#else
+#warning "Commands/WaitUntilCommand.h is deprecated; include frc/commands/WaitUntilCommand.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/commands/WaitUntilCommand.h"
diff --git a/wpilibc/src/main/native/include/Compressor.h b/wpilibc/src/main/native/include/Compressor.h
new file mode 100644
index 0000000..bfb018e
--- /dev/null
+++ b/wpilibc/src/main/native/include/Compressor.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Compressor.h is deprecated; include frc/Compressor.h instead"
+#else
+#warning "Compressor.h is deprecated; include frc/Compressor.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Compressor.h"
diff --git a/wpilibc/src/main/native/include/Controller.h b/wpilibc/src/main/native/include/Controller.h
new file mode 100644
index 0000000..b869373
--- /dev/null
+++ b/wpilibc/src/main/native/include/Controller.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Controller.h is deprecated; include frc/Controller.h instead"
+#else
+#warning "Controller.h is deprecated; include frc/Controller.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Controller.h"
diff --git a/wpilibc/src/main/native/include/ControllerPower.h b/wpilibc/src/main/native/include/ControllerPower.h
new file mode 100644
index 0000000..1469d19
--- /dev/null
+++ b/wpilibc/src/main/native/include/ControllerPower.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: ControllerPower.h is deprecated; include frc/ControllerPower.h instead"
+#else
+#warning "ControllerPower.h is deprecated; include frc/ControllerPower.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/ControllerPower.h"
diff --git a/wpilibc/src/main/native/include/Counter.h b/wpilibc/src/main/native/include/Counter.h
new file mode 100644
index 0000000..e088897
--- /dev/null
+++ b/wpilibc/src/main/native/include/Counter.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Counter.h is deprecated; include frc/Counter.h instead"
+#else
+#warning "Counter.h is deprecated; include frc/Counter.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Counter.h"
diff --git a/wpilibc/src/main/native/include/CounterBase.h b/wpilibc/src/main/native/include/CounterBase.h
new file mode 100644
index 0000000..736577f
--- /dev/null
+++ b/wpilibc/src/main/native/include/CounterBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: CounterBase.h is deprecated; include frc/CounterBase.h instead"
+#else
+#warning "CounterBase.h is deprecated; include frc/CounterBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/CounterBase.h"
diff --git a/wpilibc/src/main/native/include/DMC60.h b/wpilibc/src/main/native/include/DMC60.h
new file mode 100644
index 0000000..0fe0415
--- /dev/null
+++ b/wpilibc/src/main/native/include/DMC60.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: DMC60.h is deprecated; include frc/DMC60.h instead"
+#else
+#warning "DMC60.h is deprecated; include frc/DMC60.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/DMC60.h"
diff --git a/wpilibc/src/main/native/include/DigitalGlitchFilter.h b/wpilibc/src/main/native/include/DigitalGlitchFilter.h
new file mode 100644
index 0000000..d35c82a
--- /dev/null
+++ b/wpilibc/src/main/native/include/DigitalGlitchFilter.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: DigitalGlitchFilter.h is deprecated; include frc/DigitalGlitchFilter.h instead"
+#else
+#warning "DigitalGlitchFilter.h is deprecated; include frc/DigitalGlitchFilter.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/DigitalGlitchFilter.h"
diff --git a/wpilibc/src/main/native/include/DigitalInput.h b/wpilibc/src/main/native/include/DigitalInput.h
new file mode 100644
index 0000000..2b2a9b1
--- /dev/null
+++ b/wpilibc/src/main/native/include/DigitalInput.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: DigitalInput.h is deprecated; include frc/DigitalInput.h instead"
+#else
+#warning "DigitalInput.h is deprecated; include frc/DigitalInput.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/DigitalInput.h"
diff --git a/wpilibc/src/main/native/include/DigitalOutput.h b/wpilibc/src/main/native/include/DigitalOutput.h
new file mode 100644
index 0000000..56983c6
--- /dev/null
+++ b/wpilibc/src/main/native/include/DigitalOutput.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: DigitalOutput.h is deprecated; include frc/DigitalOutput.h instead"
+#else
+#warning "DigitalOutput.h is deprecated; include frc/DigitalOutput.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/DigitalOutput.h"
diff --git a/wpilibc/src/main/native/include/DigitalSource.h b/wpilibc/src/main/native/include/DigitalSource.h
new file mode 100644
index 0000000..9eae461
--- /dev/null
+++ b/wpilibc/src/main/native/include/DigitalSource.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: DigitalSource.h is deprecated; include frc/DigitalSource.h instead"
+#else
+#warning "DigitalSource.h is deprecated; include frc/DigitalSource.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/DigitalSource.h"
diff --git a/wpilibc/src/main/native/include/DoubleSolenoid.h b/wpilibc/src/main/native/include/DoubleSolenoid.h
new file mode 100644
index 0000000..3c1bf96
--- /dev/null
+++ b/wpilibc/src/main/native/include/DoubleSolenoid.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: DoubleSolenoid.h is deprecated; include frc/DoubleSolenoid.h instead"
+#else
+#warning "DoubleSolenoid.h is deprecated; include frc/DoubleSolenoid.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/DoubleSolenoid.h"
diff --git a/wpilibc/src/main/native/include/Drive/DifferentialDrive.h b/wpilibc/src/main/native/include/Drive/DifferentialDrive.h
new file mode 100644
index 0000000..4071d60
--- /dev/null
+++ b/wpilibc/src/main/native/include/Drive/DifferentialDrive.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Drive/DifferentialDrive.h is deprecated; include frc/drive/DifferentialDrive.h instead"
+#else
+#warning "Drive/DifferentialDrive.h is deprecated; include frc/drive/DifferentialDrive.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/drive/DifferentialDrive.h"
diff --git a/wpilibc/src/main/native/include/Drive/KilloughDrive.h b/wpilibc/src/main/native/include/Drive/KilloughDrive.h
new file mode 100644
index 0000000..fbe54a4
--- /dev/null
+++ b/wpilibc/src/main/native/include/Drive/KilloughDrive.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Drive/KilloughDrive.h is deprecated; include frc/drive/KilloughDrive.h instead"
+#else
+#warning "Drive/KilloughDrive.h is deprecated; include frc/drive/KilloughDrive.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/drive/KilloughDrive.h"
diff --git a/wpilibc/src/main/native/include/Drive/MecanumDrive.h b/wpilibc/src/main/native/include/Drive/MecanumDrive.h
new file mode 100644
index 0000000..b5a22aa
--- /dev/null
+++ b/wpilibc/src/main/native/include/Drive/MecanumDrive.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Drive/MecanumDrive.h is deprecated; include frc/drive/MecanumDrive.h instead"
+#else
+#warning "Drive/MecanumDrive.h is deprecated; include frc/drive/MecanumDrive.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/drive/MecanumDrive.h"
diff --git a/wpilibc/src/main/native/include/Drive/RobotDriveBase.h b/wpilibc/src/main/native/include/Drive/RobotDriveBase.h
new file mode 100644
index 0000000..f37ec0c
--- /dev/null
+++ b/wpilibc/src/main/native/include/Drive/RobotDriveBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Drive/RobotDriveBase.h is deprecated; include frc/drive/RobotDriveBase.h instead"
+#else
+#warning "Drive/RobotDriveBase.h is deprecated; include frc/drive/RobotDriveBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/drive/RobotDriveBase.h"
diff --git a/wpilibc/src/main/native/include/Drive/Vector2d.h b/wpilibc/src/main/native/include/Drive/Vector2d.h
new file mode 100644
index 0000000..01516ed
--- /dev/null
+++ b/wpilibc/src/main/native/include/Drive/Vector2d.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Drive/Vector2d.h is deprecated; include frc/drive/Vector2d.h instead"
+#else
+#warning "Drive/Vector2d.h is deprecated; include frc/drive/Vector2d.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/drive/Vector2d.h"
diff --git a/wpilibc/src/main/native/include/DriverStation.h b/wpilibc/src/main/native/include/DriverStation.h
new file mode 100644
index 0000000..c00adbc
--- /dev/null
+++ b/wpilibc/src/main/native/include/DriverStation.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: DriverStation.h is deprecated; include frc/DriverStation.h instead"
+#else
+#warning "DriverStation.h is deprecated; include frc/DriverStation.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/DriverStation.h"
diff --git a/wpilibc/src/main/native/include/Encoder.h b/wpilibc/src/main/native/include/Encoder.h
new file mode 100644
index 0000000..214100d
--- /dev/null
+++ b/wpilibc/src/main/native/include/Encoder.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Encoder.h is deprecated; include frc/Encoder.h instead"
+#else
+#warning "Encoder.h is deprecated; include frc/Encoder.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Encoder.h"
diff --git a/wpilibc/src/main/native/include/Error.h b/wpilibc/src/main/native/include/Error.h
new file mode 100644
index 0000000..f3fb5de
--- /dev/null
+++ b/wpilibc/src/main/native/include/Error.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Error.h is deprecated; include frc/Error.h instead"
+#else
+#warning "Error.h is deprecated; include frc/Error.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Error.h"
diff --git a/wpilibc/src/main/native/include/ErrorBase.h b/wpilibc/src/main/native/include/ErrorBase.h
new file mode 100644
index 0000000..eb300d9
--- /dev/null
+++ b/wpilibc/src/main/native/include/ErrorBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: ErrorBase.h is deprecated; include frc/ErrorBase.h instead"
+#else
+#warning "ErrorBase.h is deprecated; include frc/ErrorBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/ErrorBase.h"
diff --git a/wpilibc/src/main/native/include/Filters/Filter.h b/wpilibc/src/main/native/include/Filters/Filter.h
new file mode 100644
index 0000000..4fd382f
--- /dev/null
+++ b/wpilibc/src/main/native/include/Filters/Filter.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Filters/Filter.h is deprecated; include frc/filters/Filter.h instead"
+#else
+#warning "Filters/Filter.h is deprecated; include frc/filters/Filter.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/filters/Filter.h"
diff --git a/wpilibc/src/main/native/include/Filters/LinearDigitalFilter.h b/wpilibc/src/main/native/include/Filters/LinearDigitalFilter.h
new file mode 100644
index 0000000..b0da22c
--- /dev/null
+++ b/wpilibc/src/main/native/include/Filters/LinearDigitalFilter.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Filters/LinearDigitalFilter.h is deprecated; include frc/filters/LinearDigitalFilter.h instead"
+#else
+#warning "Filters/LinearDigitalFilter.h is deprecated; include frc/filters/LinearDigitalFilter.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/filters/LinearDigitalFilter.h"
diff --git a/wpilibc/src/main/native/include/GamepadBase.h b/wpilibc/src/main/native/include/GamepadBase.h
new file mode 100644
index 0000000..bc8d809
--- /dev/null
+++ b/wpilibc/src/main/native/include/GamepadBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: GamepadBase.h is deprecated; include frc/GamepadBase.h instead"
+#else
+#warning "GamepadBase.h is deprecated; include frc/GamepadBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/GamepadBase.h"
diff --git a/wpilibc/src/main/native/include/GearTooth.h b/wpilibc/src/main/native/include/GearTooth.h
new file mode 100644
index 0000000..2c56f95
--- /dev/null
+++ b/wpilibc/src/main/native/include/GearTooth.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: GearTooth.h is deprecated; include frc/GearTooth.h instead"
+#else
+#warning "GearTooth.h is deprecated; include frc/GearTooth.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/GearTooth.h"
diff --git a/wpilibc/src/main/native/include/GenericHID.h b/wpilibc/src/main/native/include/GenericHID.h
new file mode 100644
index 0000000..d305692
--- /dev/null
+++ b/wpilibc/src/main/native/include/GenericHID.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: GenericHID.h is deprecated; include frc/GenericHID.h instead"
+#else
+#warning "GenericHID.h is deprecated; include frc/GenericHID.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/GenericHID.h"
diff --git a/wpilibc/src/main/native/include/GyroBase.h b/wpilibc/src/main/native/include/GyroBase.h
new file mode 100644
index 0000000..f2b9097
--- /dev/null
+++ b/wpilibc/src/main/native/include/GyroBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: GyroBase.h is deprecated; include frc/GyroBase.h instead"
+#else
+#warning "GyroBase.h is deprecated; include frc/GyroBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/GyroBase.h"
diff --git a/wpilibc/src/main/native/include/I2C.h b/wpilibc/src/main/native/include/I2C.h
new file mode 100644
index 0000000..594fdaf
--- /dev/null
+++ b/wpilibc/src/main/native/include/I2C.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: I2C.h is deprecated; include frc/I2C.h instead"
+#else
+#warning "I2C.h is deprecated; include frc/I2C.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/I2C.h"
diff --git a/wpilibc/src/main/native/include/InterruptableSensorBase.h b/wpilibc/src/main/native/include/InterruptableSensorBase.h
new file mode 100644
index 0000000..43e4f74
--- /dev/null
+++ b/wpilibc/src/main/native/include/InterruptableSensorBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: InterruptableSensorBase.h is deprecated; include frc/InterruptableSensorBase.h instead"
+#else
+#warning "InterruptableSensorBase.h is deprecated; include frc/InterruptableSensorBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/InterruptableSensorBase.h"
diff --git a/wpilibc/src/main/native/include/IterativeRobot.h b/wpilibc/src/main/native/include/IterativeRobot.h
new file mode 100644
index 0000000..7ad7973
--- /dev/null
+++ b/wpilibc/src/main/native/include/IterativeRobot.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: IterativeRobot.h is deprecated; include frc/IterativeRobot.h instead"
+#else
+#warning "IterativeRobot.h is deprecated; include frc/IterativeRobot.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/IterativeRobot.h"
diff --git a/wpilibc/src/main/native/include/IterativeRobotBase.h b/wpilibc/src/main/native/include/IterativeRobotBase.h
new file mode 100644
index 0000000..e87c547
--- /dev/null
+++ b/wpilibc/src/main/native/include/IterativeRobotBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: IterativeRobotBase.h is deprecated; include frc/IterativeRobotBase.h instead"
+#else
+#warning "IterativeRobotBase.h is deprecated; include frc/IterativeRobotBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/IterativeRobotBase.h"
diff --git a/wpilibc/src/main/native/include/Jaguar.h b/wpilibc/src/main/native/include/Jaguar.h
new file mode 100644
index 0000000..7eea49d
--- /dev/null
+++ b/wpilibc/src/main/native/include/Jaguar.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Jaguar.h is deprecated; include frc/Jaguar.h instead"
+#else
+#warning "Jaguar.h is deprecated; include frc/Jaguar.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Jaguar.h"
diff --git a/wpilibc/src/main/native/include/Joystick.h b/wpilibc/src/main/native/include/Joystick.h
new file mode 100644
index 0000000..febc148
--- /dev/null
+++ b/wpilibc/src/main/native/include/Joystick.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Joystick.h is deprecated; include frc/Joystick.h instead"
+#else
+#warning "Joystick.h is deprecated; include frc/Joystick.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Joystick.h"
diff --git a/wpilibc/src/main/native/include/JoystickBase.h b/wpilibc/src/main/native/include/JoystickBase.h
new file mode 100644
index 0000000..4aa2a59
--- /dev/null
+++ b/wpilibc/src/main/native/include/JoystickBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: JoystickBase.h is deprecated; include frc/JoystickBase.h instead"
+#else
+#warning "JoystickBase.h is deprecated; include frc/JoystickBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/JoystickBase.h"
diff --git a/wpilibc/src/main/native/include/LiveWindow/LiveWindow.h b/wpilibc/src/main/native/include/LiveWindow/LiveWindow.h
new file mode 100644
index 0000000..99e7628
--- /dev/null
+++ b/wpilibc/src/main/native/include/LiveWindow/LiveWindow.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: LiveWindow/LiveWindow.h is deprecated; include frc/livewindow/LiveWindow.h instead"
+#else
+#warning "LiveWindow/LiveWindow.h is deprecated; include frc/livewindow/LiveWindow.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/livewindow/LiveWindow.h"
diff --git a/wpilibc/src/main/native/include/LiveWindow/LiveWindowSendable.h b/wpilibc/src/main/native/include/LiveWindow/LiveWindowSendable.h
new file mode 100644
index 0000000..cc8082b
--- /dev/null
+++ b/wpilibc/src/main/native/include/LiveWindow/LiveWindowSendable.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: LiveWindow/LiveWindowSendable.h is deprecated; include frc/livewindow/LiveWindowSendable.h instead"
+#else
+#warning "LiveWindow/LiveWindowSendable.h is deprecated; include frc/livewindow/LiveWindowSendable.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/livewindow/LiveWindowSendable.h"
diff --git a/wpilibc/src/main/native/include/MotorSafety.h b/wpilibc/src/main/native/include/MotorSafety.h
new file mode 100644
index 0000000..a33fd0b
--- /dev/null
+++ b/wpilibc/src/main/native/include/MotorSafety.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: MotorSafety.h is deprecated; include frc/MotorSafety.h instead"
+#else
+#warning "MotorSafety.h is deprecated; include frc/MotorSafety.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/MotorSafety.h"
diff --git a/wpilibc/src/main/native/include/NidecBrushless.h b/wpilibc/src/main/native/include/NidecBrushless.h
new file mode 100644
index 0000000..0937787
--- /dev/null
+++ b/wpilibc/src/main/native/include/NidecBrushless.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: NidecBrushless.h is deprecated; include frc/NidecBrushless.h instead"
+#else
+#warning "NidecBrushless.h is deprecated; include frc/NidecBrushless.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/NidecBrushless.h"
diff --git a/wpilibc/src/main/native/include/Notifier.h b/wpilibc/src/main/native/include/Notifier.h
new file mode 100644
index 0000000..28e6a20
--- /dev/null
+++ b/wpilibc/src/main/native/include/Notifier.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Notifier.h is deprecated; include frc/Notifier.h instead"
+#else
+#warning "Notifier.h is deprecated; include frc/Notifier.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Notifier.h"
diff --git a/wpilibc/src/main/native/include/PIDBase.h b/wpilibc/src/main/native/include/PIDBase.h
new file mode 100644
index 0000000..b9e2d50
--- /dev/null
+++ b/wpilibc/src/main/native/include/PIDBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: PIDBase.h is deprecated; include frc/PIDBase.h instead"
+#else
+#warning "PIDBase.h is deprecated; include frc/PIDBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/PIDBase.h"
diff --git a/wpilibc/src/main/native/include/PIDController.h b/wpilibc/src/main/native/include/PIDController.h
new file mode 100644
index 0000000..38777ea
--- /dev/null
+++ b/wpilibc/src/main/native/include/PIDController.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: PIDController.h is deprecated; include frc/PIDController.h instead"
+#else
+#warning "PIDController.h is deprecated; include frc/PIDController.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/PIDController.h"
diff --git a/wpilibc/src/main/native/include/PIDInterface.h b/wpilibc/src/main/native/include/PIDInterface.h
new file mode 100644
index 0000000..8e0f10e
--- /dev/null
+++ b/wpilibc/src/main/native/include/PIDInterface.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: PIDInterface.h is deprecated; include frc/PIDInterface.h instead"
+#else
+#warning "PIDInterface.h is deprecated; include frc/PIDInterface.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/PIDInterface.h"
diff --git a/wpilibc/src/main/native/include/PIDOutput.h b/wpilibc/src/main/native/include/PIDOutput.h
new file mode 100644
index 0000000..857ce0f
--- /dev/null
+++ b/wpilibc/src/main/native/include/PIDOutput.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: PIDOutput.h is deprecated; include frc/PIDOutput.h instead"
+#else
+#warning "PIDOutput.h is deprecated; include frc/PIDOutput.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/PIDOutput.h"
diff --git a/wpilibc/src/main/native/include/PIDSource.h b/wpilibc/src/main/native/include/PIDSource.h
new file mode 100644
index 0000000..29b8469
--- /dev/null
+++ b/wpilibc/src/main/native/include/PIDSource.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: PIDSource.h is deprecated; include frc/PIDSource.h instead"
+#else
+#warning "PIDSource.h is deprecated; include frc/PIDSource.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/PIDSource.h"
diff --git a/wpilibc/src/main/native/include/PWM.h b/wpilibc/src/main/native/include/PWM.h
new file mode 100644
index 0000000..989c4f7
--- /dev/null
+++ b/wpilibc/src/main/native/include/PWM.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: PWM.h is deprecated; include frc/PWM.h instead"
+#else
+#warning "PWM.h is deprecated; include frc/PWM.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/PWM.h"
diff --git a/wpilibc/src/main/native/include/PWMSpeedController.h b/wpilibc/src/main/native/include/PWMSpeedController.h
new file mode 100644
index 0000000..f15f384
--- /dev/null
+++ b/wpilibc/src/main/native/include/PWMSpeedController.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: PWMSpeedController.h is deprecated; include frc/PWMSpeedController.h instead"
+#else
+#warning "PWMSpeedController.h is deprecated; include frc/PWMSpeedController.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/PWMSpeedController.h"
diff --git a/wpilibc/src/main/native/include/PWMTalonSRX.h b/wpilibc/src/main/native/include/PWMTalonSRX.h
new file mode 100644
index 0000000..43a132a
--- /dev/null
+++ b/wpilibc/src/main/native/include/PWMTalonSRX.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: PWMTalonSRX.h is deprecated; include frc/PWMTalonSRX.h instead"
+#else
+#warning "PWMTalonSRX.h is deprecated; include frc/PWMTalonSRX.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/PWMTalonSRX.h"
diff --git a/wpilibc/src/main/native/include/PWMVictorSPX.h b/wpilibc/src/main/native/include/PWMVictorSPX.h
new file mode 100644
index 0000000..0fd6a1e
--- /dev/null
+++ b/wpilibc/src/main/native/include/PWMVictorSPX.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: PWMVictorSPX.h is deprecated; include frc/PWMVictorSPX.h instead"
+#else
+#warning "PWMVictorSPX.h is deprecated; include frc/PWMVictorSPX.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/PWMVictorSPX.h"
diff --git a/wpilibc/src/main/native/include/PowerDistributionPanel.h b/wpilibc/src/main/native/include/PowerDistributionPanel.h
new file mode 100644
index 0000000..fa4cae5
--- /dev/null
+++ b/wpilibc/src/main/native/include/PowerDistributionPanel.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: PowerDistributionPanel.h is deprecated; include frc/PowerDistributionPanel.h instead"
+#else
+#warning "PowerDistributionPanel.h is deprecated; include frc/PowerDistributionPanel.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/PowerDistributionPanel.h"
diff --git a/wpilibc/src/main/native/include/Preferences.h b/wpilibc/src/main/native/include/Preferences.h
new file mode 100644
index 0000000..3a857f3
--- /dev/null
+++ b/wpilibc/src/main/native/include/Preferences.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Preferences.h is deprecated; include frc/Preferences.h instead"
+#else
+#warning "Preferences.h is deprecated; include frc/Preferences.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Preferences.h"
diff --git a/wpilibc/src/main/native/include/Relay.h b/wpilibc/src/main/native/include/Relay.h
new file mode 100644
index 0000000..22896fe
--- /dev/null
+++ b/wpilibc/src/main/native/include/Relay.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Relay.h is deprecated; include frc/Relay.h instead"
+#else
+#warning "Relay.h is deprecated; include frc/Relay.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Relay.h"
diff --git a/wpilibc/src/main/native/include/Resource.h b/wpilibc/src/main/native/include/Resource.h
new file mode 100644
index 0000000..c314eb3
--- /dev/null
+++ b/wpilibc/src/main/native/include/Resource.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Resource.h is deprecated; include frc/Resource.h instead"
+#else
+#warning "Resource.h is deprecated; include frc/Resource.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Resource.h"
diff --git a/wpilibc/src/main/native/include/RobotBase.h b/wpilibc/src/main/native/include/RobotBase.h
new file mode 100644
index 0000000..f6faa81
--- /dev/null
+++ b/wpilibc/src/main/native/include/RobotBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: RobotBase.h is deprecated; include frc/RobotBase.h instead"
+#else
+#warning "RobotBase.h is deprecated; include frc/RobotBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/RobotBase.h"
diff --git a/wpilibc/src/main/native/include/RobotController.h b/wpilibc/src/main/native/include/RobotController.h
new file mode 100644
index 0000000..0cf64b2
--- /dev/null
+++ b/wpilibc/src/main/native/include/RobotController.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: RobotController.h is deprecated; include frc/RobotController.h instead"
+#else
+#warning "RobotController.h is deprecated; include frc/RobotController.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/RobotController.h"
diff --git a/wpilibc/src/main/native/include/RobotDrive.h b/wpilibc/src/main/native/include/RobotDrive.h
new file mode 100644
index 0000000..7b34cc4
--- /dev/null
+++ b/wpilibc/src/main/native/include/RobotDrive.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: RobotDrive.h is deprecated; include frc/RobotDrive.h instead"
+#else
+#warning "RobotDrive.h is deprecated; include frc/RobotDrive.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/RobotDrive.h"
diff --git a/wpilibc/src/main/native/include/RobotState.h b/wpilibc/src/main/native/include/RobotState.h
new file mode 100644
index 0000000..329b8ed
--- /dev/null
+++ b/wpilibc/src/main/native/include/RobotState.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: RobotState.h is deprecated; include frc/RobotState.h instead"
+#else
+#warning "RobotState.h is deprecated; include frc/RobotState.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/RobotState.h"
diff --git a/wpilibc/src/main/native/include/SD540.h b/wpilibc/src/main/native/include/SD540.h
new file mode 100644
index 0000000..8518703
--- /dev/null
+++ b/wpilibc/src/main/native/include/SD540.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: SD540.h is deprecated; include frc/SD540.h instead"
+#else
+#warning "SD540.h is deprecated; include frc/SD540.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/SD540.h"
diff --git a/wpilibc/src/main/native/include/SPI.h b/wpilibc/src/main/native/include/SPI.h
new file mode 100644
index 0000000..827a10c
--- /dev/null
+++ b/wpilibc/src/main/native/include/SPI.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: SPI.h is deprecated; include frc/SPI.h instead"
+#else
+#warning "SPI.h is deprecated; include frc/SPI.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/SPI.h"
diff --git a/wpilibc/src/main/native/include/SampleRobot.h b/wpilibc/src/main/native/include/SampleRobot.h
new file mode 100644
index 0000000..16ca36a
--- /dev/null
+++ b/wpilibc/src/main/native/include/SampleRobot.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: SampleRobot.h is deprecated; include frc/SampleRobot.h instead"
+#else
+#warning "SampleRobot.h is deprecated; include frc/SampleRobot.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/SampleRobot.h"
diff --git a/wpilibc/src/main/native/include/SensorUtil.h b/wpilibc/src/main/native/include/SensorUtil.h
new file mode 100644
index 0000000..8fd7b36
--- /dev/null
+++ b/wpilibc/src/main/native/include/SensorUtil.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: SensorUtil.h is deprecated; include frc/SensorUtil.h instead"
+#else
+#warning "SensorUtil.h is deprecated; include frc/SensorUtil.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/SensorUtil.h"
diff --git a/wpilibc/src/main/native/include/SerialPort.h b/wpilibc/src/main/native/include/SerialPort.h
new file mode 100644
index 0000000..4df02ca
--- /dev/null
+++ b/wpilibc/src/main/native/include/SerialPort.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: SerialPort.h is deprecated; include frc/SerialPort.h instead"
+#else
+#warning "SerialPort.h is deprecated; include frc/SerialPort.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/SerialPort.h"
diff --git a/wpilibc/src/main/native/include/Servo.h b/wpilibc/src/main/native/include/Servo.h
new file mode 100644
index 0000000..99cf2f2
--- /dev/null
+++ b/wpilibc/src/main/native/include/Servo.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Servo.h is deprecated; include frc/Servo.h instead"
+#else
+#warning "Servo.h is deprecated; include frc/Servo.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Servo.h"
diff --git a/wpilibc/src/main/native/include/SmartDashboard/NamedSendable.h b/wpilibc/src/main/native/include/SmartDashboard/NamedSendable.h
new file mode 100644
index 0000000..7cbcbe7
--- /dev/null
+++ b/wpilibc/src/main/native/include/SmartDashboard/NamedSendable.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: SmartDashboard/NamedSendable.h is deprecated; include frc/smartdashboard/NamedSendable.h instead"
+#else
+#warning "SmartDashboard/NamedSendable.h is deprecated; include frc/smartdashboard/NamedSendable.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/smartdashboard/NamedSendable.h"
diff --git a/wpilibc/src/main/native/include/SmartDashboard/Sendable.h b/wpilibc/src/main/native/include/SmartDashboard/Sendable.h
new file mode 100644
index 0000000..187c1ea
--- /dev/null
+++ b/wpilibc/src/main/native/include/SmartDashboard/Sendable.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: smartdashboard/Sendable.h is deprecated; include frc/smartdashboard/Sendable.h instead"
+#else
+#warning "smartdashboard/Sendable.h is deprecated; include frc/smartdashboard/Sendable.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/smartdashboard/Sendable.h"
diff --git a/wpilibc/src/main/native/include/SmartDashboard/SendableBase.h b/wpilibc/src/main/native/include/SmartDashboard/SendableBase.h
new file mode 100644
index 0000000..d898040
--- /dev/null
+++ b/wpilibc/src/main/native/include/SmartDashboard/SendableBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: smartdashboard/SendableBase.h is deprecated; include frc/smartdashboard/SendableBase.h instead"
+#else
+#warning "smartdashboard/SendableBase.h is deprecated; include frc/smartdashboard/SendableBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/smartdashboard/SendableBase.h"
diff --git a/wpilibc/src/main/native/include/SmartDashboard/SendableBuilder.h b/wpilibc/src/main/native/include/SmartDashboard/SendableBuilder.h
new file mode 100644
index 0000000..7102c35
--- /dev/null
+++ b/wpilibc/src/main/native/include/SmartDashboard/SendableBuilder.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: smartdashboard/SendableBuilder.h is deprecated; include frc/smartdashboard/SendableBuilder.h instead"
+#else
+#warning "smartdashboard/SendableBuilder.h is deprecated; include frc/smartdashboard/SendableBuilder.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/smartdashboard/SendableBuilder.h"
diff --git a/wpilibc/src/main/native/include/SmartDashboard/SendableBuilderImpl.h b/wpilibc/src/main/native/include/SmartDashboard/SendableBuilderImpl.h
new file mode 100644
index 0000000..b956309
--- /dev/null
+++ b/wpilibc/src/main/native/include/SmartDashboard/SendableBuilderImpl.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: smartdashboard/SendableBuilderImpl.h is deprecated; include frc/smartdashboard/SendableBuilderImpl.h instead"
+#else
+#warning "smartdashboard/SendableBuilderImpl.h is deprecated; include frc/smartdashboard/SendableBuilderImpl.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/smartdashboard/SendableBuilderImpl.h"
diff --git a/wpilibc/src/main/native/include/SmartDashboard/SendableChooser.h b/wpilibc/src/main/native/include/SmartDashboard/SendableChooser.h
new file mode 100644
index 0000000..5e4683f
--- /dev/null
+++ b/wpilibc/src/main/native/include/SmartDashboard/SendableChooser.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: smartdashboard/SendableChooser.h is deprecated; include frc/smartdashboard/SendableChooser.h instead"
+#else
+#warning "smartdashboard/SendableChooser.h is deprecated; include frc/smartdashboard/SendableChooser.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/smartdashboard/SendableChooser.h"
diff --git a/wpilibc/src/main/native/include/SmartDashboard/SendableChooser.inc b/wpilibc/src/main/native/include/SmartDashboard/SendableChooser.inc
new file mode 100644
index 0000000..79e8b16
--- /dev/null
+++ b/wpilibc/src/main/native/include/SmartDashboard/SendableChooser.inc
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: smartdashboard/SendableChooser.inc is deprecated; include frc/smartdashboard/SendableChooser.inc instead"
+#else
+#warning "smartdashboard/SendableChooser.inc is deprecated; include frc/smartdashboard/SendableChooser.inc instead"
+#endif
+
+// clang-format on
+
+#include "frc/smartdashboard/SendableChooser.inc"
diff --git a/wpilibc/src/main/native/include/SmartDashboard/SendableChooserBase.h b/wpilibc/src/main/native/include/SmartDashboard/SendableChooserBase.h
new file mode 100644
index 0000000..436675c
--- /dev/null
+++ b/wpilibc/src/main/native/include/SmartDashboard/SendableChooserBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: smartdashboard/SendableChooserBase.h is deprecated; include frc/smartdashboard/SendableChooserBase.h instead"
+#else
+#warning "smartdashboard/SendableChooserBase.h is deprecated; include frc/smartdashboard/SendableChooserBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/smartdashboard/SendableChooserBase.h"
diff --git a/wpilibc/src/main/native/include/SmartDashboard/SmartDashboard.h b/wpilibc/src/main/native/include/SmartDashboard/SmartDashboard.h
new file mode 100644
index 0000000..cc7c75f
--- /dev/null
+++ b/wpilibc/src/main/native/include/SmartDashboard/SmartDashboard.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: smartdashboard/SmartDashboard.h is deprecated; include frc/smartdashboard/SmartDashboard.h instead"
+#else
+#warning "smartdashboard/SmartDashboard.h is deprecated; include frc/smartdashboard/SmartDashboard.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/smartdashboard/SmartDashboard.h"
diff --git a/wpilibc/src/main/native/include/Solenoid.h b/wpilibc/src/main/native/include/Solenoid.h
new file mode 100644
index 0000000..b565188
--- /dev/null
+++ b/wpilibc/src/main/native/include/Solenoid.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Solenoid.h is deprecated; include frc/Solenoid.h instead"
+#else
+#warning "Solenoid.h is deprecated; include frc/Solenoid.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Solenoid.h"
diff --git a/wpilibc/src/main/native/include/SolenoidBase.h b/wpilibc/src/main/native/include/SolenoidBase.h
new file mode 100644
index 0000000..9678200
--- /dev/null
+++ b/wpilibc/src/main/native/include/SolenoidBase.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: SolenoidBase.h is deprecated; include frc/SolenoidBase.h instead"
+#else
+#warning "SolenoidBase.h is deprecated; include frc/SolenoidBase.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/SolenoidBase.h"
diff --git a/wpilibc/src/main/native/include/Spark.h b/wpilibc/src/main/native/include/Spark.h
new file mode 100644
index 0000000..b01c2c9
--- /dev/null
+++ b/wpilibc/src/main/native/include/Spark.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Spark.h is deprecated; include frc/Spark.h instead"
+#else
+#warning "Spark.h is deprecated; include frc/Spark.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Spark.h"
diff --git a/wpilibc/src/main/native/include/SpeedController.h b/wpilibc/src/main/native/include/SpeedController.h
new file mode 100644
index 0000000..27f0c9d
--- /dev/null
+++ b/wpilibc/src/main/native/include/SpeedController.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: SpeedController.h is deprecated; include frc/SpeedController.h instead"
+#else
+#warning "SpeedController.h is deprecated; include frc/SpeedController.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/SpeedController.h"
diff --git a/wpilibc/src/main/native/include/SpeedControllerGroup.h b/wpilibc/src/main/native/include/SpeedControllerGroup.h
new file mode 100644
index 0000000..ae387b6
--- /dev/null
+++ b/wpilibc/src/main/native/include/SpeedControllerGroup.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: SpeedControllerGroup.h is deprecated; include frc/SpeedControllerGroup.h instead"
+#else
+#warning "SpeedControllerGroup.h is deprecated; include frc/SpeedControllerGroup.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/SpeedControllerGroup.h"
diff --git a/wpilibc/src/main/native/include/SpeedControllerGroup.inc b/wpilibc/src/main/native/include/SpeedControllerGroup.inc
new file mode 100644
index 0000000..f1f6271
--- /dev/null
+++ b/wpilibc/src/main/native/include/SpeedControllerGroup.inc
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: SpeedControllerGroup.inc is deprecated; include frc/SpeedControllerGroup.inc instead"
+#else
+#warning "SpeedControllerGroup.inc is deprecated; include frc/SpeedControllerGroup.inc instead"
+#endif
+
+// clang-format on
+
+#include "frc/SpeedControllerGroup.inc"
diff --git a/wpilibc/src/main/native/include/SynchronousPID.h b/wpilibc/src/main/native/include/SynchronousPID.h
new file mode 100644
index 0000000..f2a9c53
--- /dev/null
+++ b/wpilibc/src/main/native/include/SynchronousPID.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: SynchronousPID.h is deprecated; include frc/SynchronousPID.h instead"
+#else
+#warning "SynchronousPID.h is deprecated; include frc/SynchronousPID.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/SynchronousPID.h"
diff --git a/wpilibc/src/main/native/include/Talon.h b/wpilibc/src/main/native/include/Talon.h
new file mode 100644
index 0000000..59c431c
--- /dev/null
+++ b/wpilibc/src/main/native/include/Talon.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Talon.h is deprecated; include frc/Talon.h instead"
+#else
+#warning "Talon.h is deprecated; include frc/Talon.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Talon.h"
diff --git a/wpilibc/src/main/native/include/Threads.h b/wpilibc/src/main/native/include/Threads.h
new file mode 100644
index 0000000..3a9561f
--- /dev/null
+++ b/wpilibc/src/main/native/include/Threads.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Threads.h is deprecated; include frc/Threads.h instead"
+#else
+#warning "Threads.h is deprecated; include frc/Threads.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Threads.h"
diff --git a/wpilibc/src/main/native/include/TimedRobot.h b/wpilibc/src/main/native/include/TimedRobot.h
new file mode 100644
index 0000000..3c5f393
--- /dev/null
+++ b/wpilibc/src/main/native/include/TimedRobot.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: TimedRobot.h is deprecated; include frc/TimedRobot.h instead"
+#else
+#warning "TimedRobot.h is deprecated; include frc/TimedRobot.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/TimedRobot.h"
diff --git a/wpilibc/src/main/native/include/Timer.h b/wpilibc/src/main/native/include/Timer.h
new file mode 100644
index 0000000..2df6097
--- /dev/null
+++ b/wpilibc/src/main/native/include/Timer.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Timer.h is deprecated; include frc/Timer.h instead"
+#else
+#warning "Timer.h is deprecated; include frc/Timer.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Timer.h"
diff --git a/wpilibc/src/main/native/include/Ultrasonic.h b/wpilibc/src/main/native/include/Ultrasonic.h
new file mode 100644
index 0000000..8c32ad8
--- /dev/null
+++ b/wpilibc/src/main/native/include/Ultrasonic.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Ultrasonic.h is deprecated; include frc/Ultrasonic.h instead"
+#else
+#warning "Ultrasonic.h is deprecated; include frc/Ultrasonic.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Ultrasonic.h"
diff --git a/wpilibc/src/main/native/include/Utility.h b/wpilibc/src/main/native/include/Utility.h
new file mode 100644
index 0000000..2294238
--- /dev/null
+++ b/wpilibc/src/main/native/include/Utility.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Utility.h is deprecated; include frc/Utility.h instead"
+#else
+#warning "Utility.h is deprecated; include frc/Utility.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Utility.h"
diff --git a/wpilibc/src/main/native/include/Victor.h b/wpilibc/src/main/native/include/Victor.h
new file mode 100644
index 0000000..d17df6d
--- /dev/null
+++ b/wpilibc/src/main/native/include/Victor.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Victor.h is deprecated; include frc/Victor.h instead"
+#else
+#warning "Victor.h is deprecated; include frc/Victor.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Victor.h"
diff --git a/wpilibc/src/main/native/include/VictorSP.h b/wpilibc/src/main/native/include/VictorSP.h
new file mode 100644
index 0000000..a0c8616
--- /dev/null
+++ b/wpilibc/src/main/native/include/VictorSP.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: VictorSP.h is deprecated; include frc/VictorSP.h instead"
+#else
+#warning "VictorSP.h is deprecated; include frc/VictorSP.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/VictorSP.h"
diff --git a/wpilibc/src/main/native/include/WPIErrors.h b/wpilibc/src/main/native/include/WPIErrors.h
new file mode 100644
index 0000000..6893bce
--- /dev/null
+++ b/wpilibc/src/main/native/include/WPIErrors.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: WPIErrors.h is deprecated; include frc/WPIErrors.h instead"
+#else
+#warning "WPIErrors.h is deprecated; include frc/WPIErrors.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/WPIErrors.h"
diff --git a/wpilibc/src/main/native/include/WPILib.h b/wpilibc/src/main/native/include/WPILib.h
new file mode 100644
index 0000000..ab3e608
--- /dev/null
+++ b/wpilibc/src/main/native/include/WPILib.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: WPILib.h is deprecated; include frc/WPILib.h instead"
+#else
+#warning "WPILib.h is deprecated; include frc/WPILib.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/WPILib.h"
diff --git a/wpilibc/src/main/native/include/WPILibVersion.h b/wpilibc/src/main/native/include/WPILibVersion.h
new file mode 100644
index 0000000..8aab880
--- /dev/null
+++ b/wpilibc/src/main/native/include/WPILibVersion.h
@@ -0,0 +1,14 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+/*
+ * The corresponding WPILibVersion.cpp file is autogenerated by the build
+ * system. If it does not exist, make sure that you run a build.
+ */
+extern const char* GetWPILibVersion();
diff --git a/wpilibc/src/main/native/include/Watchdog.h b/wpilibc/src/main/native/include/Watchdog.h
new file mode 100644
index 0000000..7ba2bf8
--- /dev/null
+++ b/wpilibc/src/main/native/include/Watchdog.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: Watchdog.h is deprecated; include frc/Watchdog.h instead"
+#else
+#warning "Watchdog.h is deprecated; include frc/Watchdog.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/Watchdog.h"
diff --git a/wpilibc/src/main/native/include/XboxController.h b/wpilibc/src/main/native/include/XboxController.h
new file mode 100644
index 0000000..b0abca9
--- /dev/null
+++ b/wpilibc/src/main/native/include/XboxController.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: XboxController.h is deprecated; include frc/XboxController.h instead"
+#else
+#warning "XboxController.h is deprecated; include frc/XboxController.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/XboxController.h"
diff --git a/wpilibc/src/main/native/include/circular_buffer.h b/wpilibc/src/main/native/include/circular_buffer.h
new file mode 100644
index 0000000..a150058
--- /dev/null
+++ b/wpilibc/src/main/native/include/circular_buffer.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: circular_buffer.h is deprecated; include frc/circular_buffer.h instead"
+#else
+#warning "circular_buffer.h is deprecated; include frc/circular_buffer.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/circular_buffer.h"
diff --git a/wpilibc/src/main/native/include/circular_buffer.inc b/wpilibc/src/main/native/include/circular_buffer.inc
new file mode 100644
index 0000000..417286a
--- /dev/null
+++ b/wpilibc/src/main/native/include/circular_buffer.inc
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: circular_buffer.inc is deprecated; include frc/circular_buffer.inc instead"
+#else
+#warning "circular_buffer.inc is deprecated; include frc/circular_buffer.inc instead"
+#endif
+
+// clang-format on
+
+#include "frc/circular_buffer.inc"
diff --git a/wpilibc/src/main/native/include/frc/ADXL345_I2C.h b/wpilibc/src/main/native/include/frc/ADXL345_I2C.h
new file mode 100644
index 0000000..5d5fed4
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/ADXL345_I2C.h
@@ -0,0 +1,99 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/ErrorBase.h"
+#include "frc/I2C.h"
+#include "frc/interfaces/Accelerometer.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * ADXL345 Accelerometer on I2C.
+ *
+ * This class allows access to a Analog Devices ADXL345 3-axis accelerometer on
+ * an I2C bus. This class assumes the default (not alternate) sensor address of
+ * 0x1D (7-bit address).
+ */
+class ADXL345_I2C : public ErrorBase,
+ public SendableBase,
+ public Accelerometer {
+ public:
+ enum Axes { kAxis_X = 0x00, kAxis_Y = 0x02, kAxis_Z = 0x04 };
+
+ struct AllAxes {
+ double XAxis;
+ double YAxis;
+ double ZAxis;
+ };
+
+ /**
+ * Constructs the ADXL345 Accelerometer over I2C.
+ *
+ * @param port The I2C port the accelerometer is attached to
+ * @param range The range (+ or -) that the accelerometer will measure
+ * @param deviceAddress The I2C address of the accelerometer (0x1D or 0x53)
+ */
+ explicit ADXL345_I2C(I2C::Port port, Range range = kRange_2G,
+ int deviceAddress = kAddress);
+ ~ADXL345_I2C() override = default;
+
+ ADXL345_I2C(ADXL345_I2C&&) = default;
+ ADXL345_I2C& operator=(ADXL345_I2C&&) = default;
+
+ // Accelerometer interface
+ void SetRange(Range range) override;
+ double GetX() override;
+ double GetY() override;
+ double GetZ() override;
+
+ /**
+ * Get the acceleration of one axis in Gs.
+ *
+ * @param axis The axis to read from.
+ * @return Acceleration of the ADXL345 in Gs.
+ */
+ virtual double GetAcceleration(Axes axis);
+
+ /**
+ * Get the acceleration of all axes in Gs.
+ *
+ * @return An object containing the acceleration measured on each axis of the
+ * ADXL345 in Gs.
+ */
+ virtual AllAxes GetAccelerations();
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ protected:
+ I2C m_i2c;
+
+ static constexpr int kAddress = 0x1D;
+ static constexpr int kPowerCtlRegister = 0x2D;
+ static constexpr int kDataFormatRegister = 0x31;
+ static constexpr int kDataRegister = 0x32;
+ static constexpr double kGsPerLSB = 0.00390625;
+
+ enum PowerCtlFields {
+ kPowerCtl_Link = 0x20,
+ kPowerCtl_AutoSleep = 0x10,
+ kPowerCtl_Measure = 0x08,
+ kPowerCtl_Sleep = 0x04
+ };
+
+ enum DataFormatFields {
+ kDataFormat_SelfTest = 0x80,
+ kDataFormat_SPI = 0x40,
+ kDataFormat_IntInvert = 0x20,
+ kDataFormat_FullRes = 0x08,
+ kDataFormat_Justify = 0x04
+ };
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/ADXL345_SPI.h b/wpilibc/src/main/native/include/frc/ADXL345_SPI.h
new file mode 100644
index 0000000..ac5d6d9
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/ADXL345_SPI.h
@@ -0,0 +1,98 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/ErrorBase.h"
+#include "frc/SPI.h"
+#include "frc/interfaces/Accelerometer.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * ADXL345 Accelerometer on SPI.
+ *
+ * This class allows access to an Analog Devices ADXL345 3-axis accelerometer
+ * via SPI. This class assumes the sensor is wired in 4-wire SPI mode.
+ */
+class ADXL345_SPI : public ErrorBase,
+ public SendableBase,
+ public Accelerometer {
+ public:
+ enum Axes { kAxis_X = 0x00, kAxis_Y = 0x02, kAxis_Z = 0x04 };
+
+ struct AllAxes {
+ double XAxis;
+ double YAxis;
+ double ZAxis;
+ };
+
+ /**
+ * Constructor.
+ *
+ * @param port The SPI port the accelerometer is attached to
+ * @param range The range (+ or -) that the accelerometer will measure
+ */
+ explicit ADXL345_SPI(SPI::Port port, Range range = kRange_2G);
+
+ ~ADXL345_SPI() override = default;
+
+ ADXL345_SPI(ADXL345_SPI&&) = default;
+ ADXL345_SPI& operator=(ADXL345_SPI&&) = default;
+
+ // Accelerometer interface
+ void SetRange(Range range) override;
+ double GetX() override;
+ double GetY() override;
+ double GetZ() override;
+
+ /**
+ * Get the acceleration of one axis in Gs.
+ *
+ * @param axis The axis to read from.
+ * @return Acceleration of the ADXL345 in Gs.
+ */
+ virtual double GetAcceleration(Axes axis);
+
+ /**
+ * Get the acceleration of all axes in Gs.
+ *
+ * @return An object containing the acceleration measured on each axis of the
+ * ADXL345 in Gs.
+ */
+ virtual AllAxes GetAccelerations();
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ protected:
+ SPI m_spi;
+
+ static constexpr int kPowerCtlRegister = 0x2D;
+ static constexpr int kDataFormatRegister = 0x31;
+ static constexpr int kDataRegister = 0x32;
+ static constexpr double kGsPerLSB = 0.00390625;
+
+ enum SPIAddressFields { kAddress_Read = 0x80, kAddress_MultiByte = 0x40 };
+
+ enum PowerCtlFields {
+ kPowerCtl_Link = 0x20,
+ kPowerCtl_AutoSleep = 0x10,
+ kPowerCtl_Measure = 0x08,
+ kPowerCtl_Sleep = 0x04
+ };
+
+ enum DataFormatFields {
+ kDataFormat_SelfTest = 0x80,
+ kDataFormat_SPI = 0x40,
+ kDataFormat_IntInvert = 0x20,
+ kDataFormat_FullRes = 0x08,
+ kDataFormat_Justify = 0x04
+ };
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/ADXL362.h b/wpilibc/src/main/native/include/frc/ADXL362.h
new file mode 100644
index 0000000..896af15
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/ADXL362.h
@@ -0,0 +1,81 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/ErrorBase.h"
+#include "frc/SPI.h"
+#include "frc/interfaces/Accelerometer.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * ADXL362 SPI Accelerometer.
+ *
+ * This class allows access to an Analog Devices ADXL362 3-axis accelerometer.
+ */
+class ADXL362 : public ErrorBase, public SendableBase, public Accelerometer {
+ public:
+ enum Axes { kAxis_X = 0x00, kAxis_Y = 0x02, kAxis_Z = 0x04 };
+ struct AllAxes {
+ double XAxis;
+ double YAxis;
+ double ZAxis;
+ };
+
+ public:
+ /**
+ * Constructor. Uses the onboard CS1.
+ *
+ * @param range The range (+ or -) that the accelerometer will measure.
+ */
+ explicit ADXL362(Range range = kRange_2G);
+
+ /**
+ * Constructor.
+ *
+ * @param port The SPI port the accelerometer is attached to
+ * @param range The range (+ or -) that the accelerometer will measure.
+ */
+ explicit ADXL362(SPI::Port port, Range range = kRange_2G);
+
+ virtual ~ADXL362() = default;
+
+ ADXL362(ADXL362&&) = default;
+ ADXL362& operator=(ADXL362&&) = default;
+
+ // Accelerometer interface
+ void SetRange(Range range) override;
+ double GetX() override;
+ double GetY() override;
+ double GetZ() override;
+
+ /**
+ * Get the acceleration of one axis in Gs.
+ *
+ * @param axis The axis to read from.
+ * @return Acceleration of the ADXL362 in Gs.
+ */
+ virtual double GetAcceleration(Axes axis);
+
+ /**
+ * Get the acceleration of all axes in Gs.
+ *
+ * @return An object containing the acceleration measured on each axis of the
+ * ADXL362 in Gs.
+ */
+ virtual AllAxes GetAccelerations();
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ SPI m_spi;
+ double m_gsPerLSB = 0.001;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/ADXRS450_Gyro.h b/wpilibc/src/main/native/include/frc/ADXRS450_Gyro.h
new file mode 100644
index 0000000..e1b70e2
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/ADXRS450_Gyro.h
@@ -0,0 +1,100 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include "frc/GyroBase.h"
+#include "frc/SPI.h"
+
+namespace frc {
+
+/**
+ * Use a rate gyro to return the robots heading relative to a starting position.
+ *
+ * The Gyro class tracks the robots heading based on the starting position. As
+ * the robot rotates the new heading is computed by integrating the rate of
+ * rotation returned by the sensor. When the class is instantiated, it does a
+ * short calibration routine where it samples the gyro while at rest to
+ * determine the default offset. This is subtracted from each sample to
+ * determine the heading.
+ *
+ * This class is for the digital ADXRS450 gyro sensor that connects via SPI.
+ */
+class ADXRS450_Gyro : public GyroBase {
+ public:
+ /**
+ * Gyro constructor on onboard CS0.
+ */
+ ADXRS450_Gyro();
+
+ /**
+ * Gyro constructor on the specified SPI port.
+ *
+ * @param port The SPI port the gyro is attached to.
+ */
+ explicit ADXRS450_Gyro(SPI::Port port);
+
+ virtual ~ADXRS450_Gyro() = default;
+
+ ADXRS450_Gyro(ADXRS450_Gyro&&) = default;
+ ADXRS450_Gyro& operator=(ADXRS450_Gyro&&) = default;
+
+ /**
+ * Return the actual angle in degrees that the robot is currently facing.
+ *
+ * The angle is based on the current accumulator value corrected by the
+ * oversampling rate, the gyro type and the A/D calibration values.
+ * The angle is continuous, that is it will continue from 360->361 degrees.
+ * This allows algorithms that wouldn't want to see a discontinuity in the
+ * gyro output as it sweeps from 360 to 0 on the second time around.
+ *
+ * @return the current heading of the robot in degrees. This heading is based
+ * on integration of the returned rate from the gyro.
+ */
+ double GetAngle() const override;
+
+ /**
+ * Return the rate of rotation of the gyro
+ *
+ * The rate is based on the most recent reading of the gyro analog value
+ *
+ * @return the current rate in degrees per second
+ */
+ double GetRate() const override;
+
+ /**
+ * Reset the gyro.
+ *
+ * Resets the gyro to a heading of zero. This can be used if there is
+ * significant drift in the gyro and it needs to be recalibrated after it has
+ * been running.
+ */
+ void Reset() override;
+
+ /**
+ * Initialize the gyro.
+ *
+ * Calibrate the gyro by running for a number of samples and computing the
+ * center value. Then use the center value as the Accumulator center value for
+ * subsequent measurements.
+ *
+ * It's important to make sure that the robot is not moving while the
+ * centering calculations are in progress, this is typically done when the
+ * robot is first turned on while it's sitting at rest before the competition
+ * starts.
+ */
+ void Calibrate() override;
+
+ private:
+ SPI m_spi;
+
+ uint16_t ReadRegister(int reg);
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/AnalogAccelerometer.h b/wpilibc/src/main/native/include/frc/AnalogAccelerometer.h
new file mode 100644
index 0000000..80dc98e
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/AnalogAccelerometer.h
@@ -0,0 +1,119 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include "frc/AnalogInput.h"
+#include "frc/ErrorBase.h"
+#include "frc/PIDSource.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * Handle operation of an analog accelerometer.
+ *
+ * The accelerometer reads acceleration directly through the sensor. Many
+ * sensors have multiple axis and can be treated as multiple devices. Each is
+ * calibrated by finding the center value over a period of time.
+ */
+class AnalogAccelerometer : public ErrorBase,
+ public SendableBase,
+ public PIDSource {
+ public:
+ /**
+ * Create a new instance of an accelerometer.
+ *
+ * The constructor allocates desired analog input.
+ *
+ * @param channel The channel number for the analog input the accelerometer is
+ * connected to
+ */
+ explicit AnalogAccelerometer(int channel);
+
+ /**
+ * Create a new instance of Accelerometer from an existing AnalogInput.
+ *
+ * Make a new instance of accelerometer given an AnalogInput. This is
+ * particularly useful if the port is going to be read as an analog channel as
+ * well as through the Accelerometer class.
+ *
+ * @param channel The existing AnalogInput object for the analog input the
+ * accelerometer is connected to
+ */
+ explicit AnalogAccelerometer(AnalogInput* channel);
+
+ /**
+ * Create a new instance of Accelerometer from an existing AnalogInput.
+ *
+ * Make a new instance of accelerometer given an AnalogInput. This is
+ * particularly useful if the port is going to be read as an analog channel as
+ * well as through the Accelerometer class.
+ *
+ * @param channel The existing AnalogInput object for the analog input the
+ * accelerometer is connected to
+ */
+ explicit AnalogAccelerometer(std::shared_ptr<AnalogInput> channel);
+
+ ~AnalogAccelerometer() override = default;
+
+ AnalogAccelerometer(AnalogAccelerometer&&) = default;
+ AnalogAccelerometer& operator=(AnalogAccelerometer&&) = default;
+
+ /**
+ * Return the acceleration in Gs.
+ *
+ * The acceleration is returned units of Gs.
+ *
+ * @return The current acceleration of the sensor in Gs.
+ */
+ double GetAcceleration() const;
+
+ /**
+ * Set the accelerometer sensitivity.
+ *
+ * This sets the sensitivity of the accelerometer used for calculating the
+ * acceleration. The sensitivity varies by accelerometer model. There are
+ * constants defined for various models.
+ *
+ * @param sensitivity The sensitivity of accelerometer in Volts per G.
+ */
+ void SetSensitivity(double sensitivity);
+
+ /**
+ * Set the voltage that corresponds to 0 G.
+ *
+ * The zero G voltage varies by accelerometer model. There are constants
+ * defined for various models.
+ *
+ * @param zero The zero G voltage.
+ */
+ void SetZero(double zero);
+
+ /**
+ * Get the Acceleration for the PID Source parent.
+ *
+ * @return The current acceleration in Gs.
+ */
+ double PIDGet() override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ /**
+ * Common function for initializing the accelerometer.
+ */
+ void InitAccelerometer();
+
+ std::shared_ptr<AnalogInput> m_analogInput;
+ double m_voltsPerG = 1.0;
+ double m_zeroGVoltage = 2.5;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/AnalogGyro.h b/wpilibc/src/main/native/include/frc/AnalogGyro.h
new file mode 100644
index 0000000..9e18d89
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/AnalogGyro.h
@@ -0,0 +1,194 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <hal/Types.h>
+
+#include "frc/GyroBase.h"
+
+namespace frc {
+
+class AnalogInput;
+
+/**
+ * Use a rate gyro to return the robots heading relative to a starting position.
+ * The Gyro class tracks the robots heading based on the starting position. As
+ * the robot rotates the new heading is computed by integrating the rate of
+ * rotation returned by the sensor. When the class is instantiated, it does a
+ * short calibration routine where it samples the gyro while at rest to
+ * determine the default offset. This is subtracted from each sample to
+ * determine the heading. This gyro class must be used with a channel that is
+ * assigned one of the Analog accumulators from the FPGA. See AnalogInput for
+ * the current accumulator assignments.
+ *
+ * This class is for gyro sensors that connect to an analog input.
+ */
+class AnalogGyro : public GyroBase {
+ public:
+ static constexpr int kOversampleBits = 10;
+ static constexpr int kAverageBits = 0;
+ static constexpr double kSamplesPerSecond = 50.0;
+ static constexpr double kCalibrationSampleTime = 5.0;
+ static constexpr double kDefaultVoltsPerDegreePerSecond = 0.007;
+
+ /**
+ * Gyro constructor using the Analog Input channel number.
+ *
+ * @param channel The analog channel the gyro is connected to. Gyros can only
+ * be used on on-board Analog Inputs 0-1.
+ */
+ explicit AnalogGyro(int channel);
+
+ /**
+ * Gyro constructor with a precreated AnalogInput object.
+ *
+ * Use this constructor when the analog channel needs to be shared.
+ * This object will not clean up the AnalogInput object when using this
+ * constructor.
+ *
+ * Gyros can only be used on on-board channels 0-1.
+ *
+ * @param channel A pointer to the AnalogInput object that the gyro is
+ * connected to.
+ */
+ explicit AnalogGyro(AnalogInput* channel);
+
+ /**
+ * Gyro constructor with a precreated AnalogInput object.
+ *
+ * Use this constructor when the analog channel needs to be shared.
+ * This object will not clean up the AnalogInput object when using this
+ * constructor.
+ *
+ * @param channel A pointer to the AnalogInput object that the gyro is
+ * connected to.
+ */
+ explicit AnalogGyro(std::shared_ptr<AnalogInput> channel);
+
+ /**
+ * Gyro constructor using the Analog Input channel number with parameters for
+ * presetting the center and offset values. Bypasses calibration.
+ *
+ * @param channel The analog channel the gyro is connected to. Gyros can only
+ * be used on on-board Analog Inputs 0-1.
+ * @param center Preset uncalibrated value to use as the accumulator center
+ * value.
+ * @param offset Preset uncalibrated value to use as the gyro offset.
+ */
+ AnalogGyro(int channel, int center, double offset);
+
+ /**
+ * Gyro constructor with a precreated AnalogInput object and calibrated
+ * parameters.
+ *
+ * Use this constructor when the analog channel needs to be shared.
+ * This object will not clean up the AnalogInput object when using this
+ * constructor.
+ *
+ * @param channel A pointer to the AnalogInput object that the gyro is
+ * connected to.
+ * @param center Preset uncalibrated value to use as the accumulator center
+ * value.
+ * @param offset Preset uncalibrated value to use as the gyro offset.
+ */
+ AnalogGyro(std::shared_ptr<AnalogInput> channel, int center, double offset);
+
+ virtual ~AnalogGyro();
+
+ AnalogGyro(AnalogGyro&& rhs);
+ AnalogGyro& operator=(AnalogGyro&& rhs);
+
+ /**
+ * Return the actual angle in degrees that the robot is currently facing.
+ *
+ * The angle is based on the current accumulator value corrected by the
+ * oversampling rate, the gyro type and the A/D calibration values. The angle
+ * is continuous, that is it will continue from 360->361 degrees. This allows
+ * algorithms that wouldn't want to see a discontinuity in the gyro output as
+ * it sweeps from 360 to 0 on the second time around.
+ *
+ * @return The current heading of the robot in degrees. This heading is based
+ * on integration of the returned rate from the gyro.
+ */
+ double GetAngle() const override;
+
+ /**
+ * Return the rate of rotation of the gyro
+ *
+ * The rate is based on the most recent reading of the gyro analog value
+ *
+ * @return the current rate in degrees per second
+ */
+ double GetRate() const override;
+
+ /**
+ * Return the gyro center value. If run after calibration,
+ * the center value can be used as a preset later.
+ *
+ * @return the current center value
+ */
+ virtual int GetCenter() const;
+
+ /**
+ * Return the gyro offset value. If run after calibration,
+ * the offset value can be used as a preset later.
+ *
+ * @return the current offset value
+ */
+ virtual double GetOffset() const;
+
+ /**
+ * Set the gyro sensitivity.
+ *
+ * This takes the number of volts/degree/second sensitivity of the gyro and
+ * uses it in subsequent calculations to allow the code to work with multiple
+ * gyros. This value is typically found in the gyro datasheet.
+ *
+ * @param voltsPerDegreePerSecond The sensitivity in Volts/degree/second
+ */
+ void SetSensitivity(double voltsPerDegreePerSecond);
+
+ /**
+ * Set the size of the neutral zone.
+ *
+ * Any voltage from the gyro less than this amount from the center is
+ * considered stationary. Setting a deadband will decrease the amount of
+ * drift when the gyro isn't rotating, but will make it less accurate.
+ *
+ * @param volts The size of the deadband in volts
+ */
+ void SetDeadband(double volts);
+
+ /**
+ * Reset the gyro.
+ *
+ * Resets the gyro to a heading of zero. This can be used if there is
+ * significant drift in the gyro and it needs to be recalibrated after it has
+ * been running.
+ */
+ void Reset() override;
+
+ /**
+ * Initialize the gyro.
+ *
+ * Calibration is handled by Calibrate().
+ */
+ virtual void InitGyro();
+
+ void Calibrate() override;
+
+ protected:
+ std::shared_ptr<AnalogInput> m_analog;
+
+ private:
+ HAL_GyroHandle m_gyroHandle = HAL_kInvalidHandle;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/AnalogInput.h b/wpilibc/src/main/native/include/frc/AnalogInput.h
new file mode 100644
index 0000000..97ce2a8
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/AnalogInput.h
@@ -0,0 +1,291 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <hal/Types.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/PIDSource.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * Analog input class.
+ *
+ * Connected to each analog channel is an averaging and oversampling engine.
+ * This engine accumulates the specified ( by SetAverageBits() and
+ * SetOversampleBits() ) number of samples before returning a new value. This is
+ * not a sliding window average. The only difference between the oversampled
+ * samples and the averaged samples is that the oversampled samples are simply
+ * accumulated effectively increasing the resolution, while the averaged samples
+ * are divided by the number of samples to retain the resolution, but get more
+ * stable values.
+ */
+class AnalogInput : public ErrorBase, public SendableBase, public PIDSource {
+ friend class AnalogTrigger;
+ friend class AnalogGyro;
+
+ public:
+ static constexpr int kAccumulatorModuleNumber = 1;
+ static constexpr int kAccumulatorNumChannels = 2;
+ static constexpr int kAccumulatorChannels[kAccumulatorNumChannels] = {0, 1};
+
+ /**
+ * Construct an analog input.
+ *
+ * @param channel The channel number on the roboRIO to represent. 0-3 are
+ * on-board 4-7 are on the MXP port.
+ */
+ explicit AnalogInput(int channel);
+
+ ~AnalogInput() override;
+
+ AnalogInput(AnalogInput&& rhs);
+ AnalogInput& operator=(AnalogInput&& rhs);
+
+ /**
+ * Get a sample straight from this channel.
+ *
+ * The sample is a 12-bit value representing the 0V to 5V range of the A/D
+ * converter in the module. The units are in A/D converter codes. Use
+ * GetVoltage() to get the analog value in calibrated units.
+ *
+ * @return A sample straight from this channel.
+ */
+ int GetValue() const;
+
+ /**
+ * Get a sample from the output of the oversample and average engine for this
+ * channel.
+ *
+ * The sample is 12-bit + the bits configured in SetOversampleBits().
+ * The value configured in SetAverageBits() will cause this value to be
+ * averaged 2**bits number of samples.
+ *
+ * This is not a sliding window. The sample will not change until
+ * 2**(OversampleBits + AverageBits) samples have been acquired from the
+ * module on this channel.
+ *
+ * Use GetAverageVoltage() to get the analog value in calibrated units.
+ *
+ * @return A sample from the oversample and average engine for this channel.
+ */
+ int GetAverageValue() const;
+
+ /**
+ * Get a scaled sample straight from this channel.
+ *
+ * The value is scaled to units of Volts using the calibrated scaling data
+ * from GetLSBWeight() and GetOffset().
+ *
+ * @return A scaled sample straight from this channel.
+ */
+ double GetVoltage() const;
+
+ /**
+ * Get a scaled sample from the output of the oversample and average engine
+ * for this channel.
+ *
+ * The value is scaled to units of Volts using the calibrated scaling data
+ * from GetLSBWeight() and GetOffset().
+ *
+ * Using oversampling will cause this value to be higher resolution, but it
+ * will update more slowly.
+ *
+ * Using averaging will cause this value to be more stable, but it will update
+ * more slowly.
+ *
+ * @return A scaled sample from the output of the oversample and average
+ * engine for this channel.
+ */
+ double GetAverageVoltage() const;
+
+ /**
+ * Get the channel number.
+ *
+ * @return The channel number.
+ */
+ int GetChannel() const;
+
+ /**
+ * Set the number of averaging bits.
+ *
+ * This sets the number of averaging bits. The actual number of averaged
+ * samples is 2^bits.
+ *
+ * Use averaging to improve the stability of your measurement at the expense
+ * of sampling rate. The averaging is done automatically in the FPGA.
+ *
+ * @param bits Number of bits of averaging.
+ */
+ void SetAverageBits(int bits);
+
+ /**
+ * Get the number of averaging bits previously configured.
+ *
+ * This gets the number of averaging bits from the FPGA. The actual number of
+ * averaged samples is 2^bits. The averaging is done automatically in the
+ * FPGA.
+ *
+ * @return Number of bits of averaging previously configured.
+ */
+ int GetAverageBits() const;
+
+ /**
+ * Set the number of oversample bits.
+ *
+ * This sets the number of oversample bits. The actual number of oversampled
+ * values is 2^bits. Use oversampling to improve the resolution of your
+ * measurements at the expense of sampling rate. The oversampling is done
+ * automatically in the FPGA.
+ *
+ * @param bits Number of bits of oversampling.
+ */
+ void SetOversampleBits(int bits);
+
+ /**
+ * Get the number of oversample bits previously configured.
+ *
+ * This gets the number of oversample bits from the FPGA. The actual number of
+ * oversampled values is 2^bits. The oversampling is done automatically in the
+ * FPGA.
+ *
+ * @return Number of bits of oversampling previously configured.
+ */
+ int GetOversampleBits() const;
+
+ /**
+ * Get the factory scaling least significant bit weight constant.
+ *
+ * Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
+ *
+ * @return Least significant bit weight.
+ */
+ int GetLSBWeight() const;
+
+ /**
+ * Get the factory scaling offset constant.
+ *
+ * Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
+ *
+ * @return Offset constant.
+ */
+ int GetOffset() const;
+
+ /**
+ * Is the channel attached to an accumulator.
+ *
+ * @return The analog input is attached to an accumulator.
+ */
+ bool IsAccumulatorChannel() const;
+
+ /**
+ * Initialize the accumulator.
+ */
+ void InitAccumulator();
+
+ /**
+ * Set an initial value for the accumulator.
+ *
+ * This will be added to all values returned to the user.
+ *
+ * @param initialValue The value that the accumulator should start from when
+ * reset.
+ */
+ void SetAccumulatorInitialValue(int64_t value);
+
+ /**
+ * Resets the accumulator to the initial value.
+ */
+ void ResetAccumulator();
+
+ /**
+ * Set the center value of the accumulator.
+ *
+ * The center value is subtracted from each A/D value before it is added to
+ * the accumulator. This is used for the center value of devices like gyros
+ * and accelerometers to take the device offset into account when integrating.
+ *
+ * This center value is based on the output of the oversampled and averaged
+ * source from the accumulator channel. Because of this, any non-zero
+ * oversample bits will affect the size of the value for this field.
+ */
+ void SetAccumulatorCenter(int center);
+
+ /**
+ * Set the accumulator's deadband.
+ */
+ void SetAccumulatorDeadband(int deadband);
+
+ /**
+ * Read the accumulated value.
+ *
+ * Read the value that has been accumulating.
+ * The accumulator is attached after the oversample and average engine.
+ *
+ * @return The 64-bit value accumulated since the last Reset().
+ */
+ int64_t GetAccumulatorValue() const;
+
+ /**
+ * Read the number of accumulated values.
+ *
+ * Read the count of the accumulated values since the accumulator was last
+ * Reset().
+ *
+ * @return The number of times samples from the channel were accumulated.
+ */
+ int64_t GetAccumulatorCount() const;
+
+ /**
+ * Read the accumulated value and the number of accumulated values atomically.
+ *
+ * This function reads the value and count from the FPGA atomically.
+ * This can be used for averaging.
+ *
+ * @param value Reference to the 64-bit accumulated output.
+ * @param count Reference to the number of accumulation cycles.
+ */
+ void GetAccumulatorOutput(int64_t& value, int64_t& count) const;
+
+ /**
+ * Set the sample rate per channel for all analog channels.
+ *
+ * The maximum rate is 500kS/s divided by the number of channels in use.
+ * This is 62500 samples/s per channel.
+ *
+ * @param samplesPerSecond The number of samples per second.
+ */
+ static void SetSampleRate(double samplesPerSecond);
+
+ /**
+ * Get the current sample rate for all channels
+ *
+ * @return Sample rate.
+ */
+ static double GetSampleRate();
+
+ /**
+ * Get the Average value for the PID Source base object.
+ *
+ * @return The average voltage.
+ */
+ double PIDGet() override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ int m_channel;
+ HAL_AnalogInputHandle m_port = HAL_kInvalidHandle;
+ int64_t m_accumulatorOffset;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/AnalogOutput.h b/wpilibc/src/main/native/include/frc/AnalogOutput.h
new file mode 100644
index 0000000..3c7b44e
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/AnalogOutput.h
@@ -0,0 +1,62 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <hal/Types.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * MXP analog output class.
+ */
+class AnalogOutput : public ErrorBase, public SendableBase {
+ public:
+ /**
+ * Construct an analog output on the given channel.
+ *
+ * All analog outputs are located on the MXP port.
+ *
+ * @param channel The channel number on the roboRIO to represent.
+ */
+ explicit AnalogOutput(int channel);
+
+ ~AnalogOutput() override;
+
+ AnalogOutput(AnalogOutput&& rhs);
+ AnalogOutput& operator=(AnalogOutput&& rhs);
+
+ /**
+ * Set the value of the analog output.
+ *
+ * @param voltage The output value in Volts, from 0.0 to +5.0
+ */
+ void SetVoltage(double voltage);
+
+ /**
+ * Get the voltage of the analog output
+ *
+ * @return The value in Volts, from 0.0 to +5.0
+ */
+ double GetVoltage() const;
+
+ /**
+ * Get the channel of this AnalogOutput.
+ */
+ int GetChannel();
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ protected:
+ int m_channel;
+ HAL_AnalogOutputHandle m_port = HAL_kInvalidHandle;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/AnalogPotentiometer.h b/wpilibc/src/main/native/include/frc/AnalogPotentiometer.h
new file mode 100644
index 0000000..a937c69
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/AnalogPotentiometer.h
@@ -0,0 +1,122 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include "frc/AnalogInput.h"
+#include "frc/ErrorBase.h"
+#include "frc/interfaces/Potentiometer.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * Class for reading analog potentiometers. Analog potentiometers read in an
+ * analog voltage that corresponds to a position. The position is in whichever
+ * units you choose, by way of the scaling and offset constants passed to the
+ * constructor.
+ */
+class AnalogPotentiometer : public ErrorBase,
+ public SendableBase,
+ public Potentiometer {
+ public:
+ /**
+ * Construct an Analog Potentiometer object from a channel number.
+ *
+ * Use the fullRange and offset values so that the output produces meaningful
+ * values. I.E: you have a 270 degree potentiometer and you want the output to
+ * be degrees with the halfway point as 0 degrees. The fullRange value is
+ * 270.0 degrees and the offset is -135.0 since the halfway point after
+ * scaling is 135 degrees.
+ *
+ * This will calculate the result from the fullRange times the fraction of the
+ * supply voltage, plus the offset.
+ *
+ * @param channel The channel number on the roboRIO to represent. 0-3 are
+ * on-board 4-7 are on the MXP port.
+ * @param fullRange The angular value (in desired units) representing the full
+ * 0-5V range of the input.
+ * @param offset The angular value (in desired units) representing the
+ * angular output at 0V.
+ */
+ explicit AnalogPotentiometer(int channel, double fullRange = 1.0,
+ double offset = 0.0);
+
+ /**
+ * Construct an Analog Potentiometer object from an existing Analog Input
+ * pointer.
+ *
+ * Use the fullRange and offset values so that the output produces meaningful
+ * values. I.E: you have a 270 degree potentiometer and you want the output to
+ * be degrees with the halfway point as 0 degrees. The fullRange value is
+ * 270.0 degrees and the offset is -135.0 since the halfway point after
+ * scaling is 135 degrees.
+ *
+ * This will calculate the result from the fullRange times the fraction of the
+ * supply voltage, plus the offset.
+ *
+ * @param channel The existing Analog Input pointer
+ * @param fullRange The angular value (in desired units) representing the full
+ * 0-5V range of the input.
+ * @param offset The angular value (in desired units) representing the
+ * angular output at 0V.
+ */
+ explicit AnalogPotentiometer(AnalogInput* input, double fullRange = 1.0,
+ double offset = 0.0);
+
+ /**
+ * Construct an Analog Potentiometer object from an existing Analog Input
+ * pointer.
+ *
+ * Use the fullRange and offset values so that the output produces meaningful
+ * values. I.E: you have a 270 degree potentiometer and you want the output to
+ * be degrees with the halfway point as 0 degrees. The fullRange value is
+ * 270.0 degrees and the offset is -135.0 since the halfway point after
+ * scaling is 135 degrees.
+ *
+ * This will calculate the result from the fullRange times the fraction of the
+ * supply voltage, plus the offset.
+ *
+ * @param channel The existing Analog Input pointer
+ * @param fullRange The angular value (in desired units) representing the full
+ * 0-5V range of the input.
+ * @param offset The angular value (in desired units) representing the
+ * angular output at 0V.
+ */
+ explicit AnalogPotentiometer(std::shared_ptr<AnalogInput> input,
+ double fullRange = 1.0, double offset = 0.0);
+
+ ~AnalogPotentiometer() override = default;
+
+ AnalogPotentiometer(AnalogPotentiometer&&) = default;
+ AnalogPotentiometer& operator=(AnalogPotentiometer&&) = default;
+
+ /**
+ * Get the current reading of the potentiomer.
+ *
+ * @return The current position of the potentiometer (in the units used for
+ * fullRange and offset).
+ */
+ double Get() const override;
+
+ /**
+ * Implement the PIDSource interface.
+ *
+ * @return The current reading.
+ */
+ double PIDGet() override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ std::shared_ptr<AnalogInput> m_analog_input;
+ double m_fullRange, m_offset;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/AnalogTrigger.h b/wpilibc/src/main/native/include/frc/AnalogTrigger.h
new file mode 100644
index 0000000..beb48fc
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/AnalogTrigger.h
@@ -0,0 +1,144 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <hal/Types.h>
+
+#include "frc/AnalogTriggerOutput.h"
+#include "frc/ErrorBase.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class AnalogInput;
+
+class AnalogTrigger : public ErrorBase, public SendableBase {
+ friend class AnalogTriggerOutput;
+
+ public:
+ /**
+ * Constructor for an analog trigger given a channel number.
+ *
+ * @param channel The channel number on the roboRIO to represent. 0-3 are
+ * on-board 4-7 are on the MXP port.
+ */
+ explicit AnalogTrigger(int channel);
+
+ /**
+ * Construct an analog trigger given an analog input.
+ *
+ * This should be used in the case of sharing an analog channel between the
+ * trigger and an analog input object.
+ *
+ * @param channel The pointer to the existing AnalogInput object
+ */
+ explicit AnalogTrigger(AnalogInput* channel);
+
+ ~AnalogTrigger() override;
+
+ AnalogTrigger(AnalogTrigger&& rhs);
+ AnalogTrigger& operator=(AnalogTrigger&& rhs);
+
+ /**
+ * Set the upper and lower limits of the analog trigger.
+ *
+ * The limits are given as floating point voltage values.
+ *
+ * @param lower The lower limit of the trigger in Volts.
+ * @param upper The upper limit of the trigger in Volts.
+ */
+ void SetLimitsVoltage(double lower, double upper);
+
+ /**
+ * Set the upper and lower limits of the analog trigger.
+ *
+ * The limits are given in ADC codes. If oversampling is used, the units must
+ * be scaled appropriately.
+ *
+ * @param lower The lower limit of the trigger in ADC codes (12-bit values).
+ * @param upper The upper limit of the trigger in ADC codes (12-bit values).
+ */
+ void SetLimitsRaw(int lower, int upper);
+
+ /**
+ * Configure the analog trigger to use the averaged vs. raw values.
+ *
+ * If the value is true, then the averaged value is selected for the analog
+ * trigger, otherwise the immediate value is used.
+ *
+ * @param useAveragedValue If true, use the Averaged value, otherwise use the
+ * instantaneous reading
+ */
+ void SetAveraged(bool useAveragedValue);
+
+ /**
+ * Configure the analog trigger to use a filtered value.
+ *
+ * The analog trigger will operate with a 3 point average rejection filter.
+ * This is designed to help with 360 degree pot applications for the period
+ * where the pot crosses through zero.
+ *
+ * @param useFilteredValue If true, use the 3 point rejection filter,
+ * otherwise use the unfiltered value
+ */
+ void SetFiltered(bool useFilteredValue);
+
+ /**
+ * Return the index of the analog trigger.
+ *
+ * This is the FPGA index of this analog trigger instance.
+ *
+ * @return The index of the analog trigger.
+ */
+ int GetIndex() const;
+
+ /**
+ * Return the InWindow output of the analog trigger.
+ *
+ * True if the analog input is between the upper and lower limits.
+ *
+ * @return True if the analog input is between the upper and lower limits.
+ */
+ bool GetInWindow();
+
+ /**
+ * Return the TriggerState output of the analog trigger.
+ *
+ * True if above upper limit.
+ * False if below lower limit.
+ * If in Hysteresis, maintain previous state.
+ *
+ * @return True if above upper limit. False if below lower limit. If in
+ * Hysteresis, maintain previous state.
+ */
+ bool GetTriggerState();
+
+ /**
+ * Creates an AnalogTriggerOutput object.
+ *
+ * Gets an output object that can be used for routing. Caller is responsible
+ * for deleting the AnalogTriggerOutput object.
+ *
+ * @param type An enum of the type of output object to create.
+ * @return A pointer to a new AnalogTriggerOutput object.
+ */
+ std::shared_ptr<AnalogTriggerOutput> CreateOutput(
+ AnalogTriggerType type) const;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ int m_index;
+ HAL_AnalogTriggerHandle m_trigger = HAL_kInvalidHandle;
+ AnalogInput* m_analogInput = nullptr;
+ bool m_ownsAnalog = false;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/AnalogTriggerOutput.h b/wpilibc/src/main/native/include/frc/AnalogTriggerOutput.h
new file mode 100644
index 0000000..fc3d8f2
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/AnalogTriggerOutput.h
@@ -0,0 +1,109 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/DigitalSource.h"
+
+namespace frc {
+
+class AnalogTrigger;
+
+/**
+ * Class to represent a specific output from an analog trigger.
+ *
+ * This class is used to get the current output value and also as a
+ * DigitalSource to provide routing of an output to digital subsystems on the
+ * FPGA such as Counter, Encoder, and Interrupt.
+ *
+ * The TriggerState output indicates the primary output value of the trigger.
+ * If the analog signal is less than the lower limit, the output is false. If
+ * the analog value is greater than the upper limit, then the output is true.
+ * If the analog value is in between, then the trigger output state maintains
+ * its most recent value.
+ *
+ * The InWindow output indicates whether or not the analog signal is inside the
+ * range defined by the limits.
+ *
+ * The RisingPulse and FallingPulse outputs detect an instantaneous transition
+ * from above the upper limit to below the lower limit, and vise versa. These
+ * pulses represent a rollover condition of a sensor and can be routed to an up
+ * / down counter or to interrupts. Because the outputs generate a pulse, they
+ * cannot be read directly. To help ensure that a rollover condition is not
+ * missed, there is an average rejection filter available that operates on the
+ * upper 8 bits of a 12 bit number and selects the nearest outlyer of 3 samples.
+ * This will reject a sample that is (due to averaging or sampling) errantly
+ * between the two limits. This filter will fail if more than one sample in a
+ * row is errantly in between the two limits. You may see this problem if
+ * attempting to use this feature with a mechanical rollover sensor, such as a
+ * 360 degree no-stop potentiometer without signal conditioning, because the
+ * rollover transition is not sharp / clean enough. Using the averaging engine
+ * may help with this, but rotational speeds of the sensor will then be limited.
+ */
+class AnalogTriggerOutput : public DigitalSource {
+ friend class AnalogTrigger;
+
+ public:
+ ~AnalogTriggerOutput() override;
+
+ AnalogTriggerOutput(AnalogTriggerOutput&&) = default;
+ AnalogTriggerOutput& operator=(AnalogTriggerOutput&&) = default;
+
+ /**
+ * Get the state of the analog trigger output.
+ *
+ * @return The state of the analog trigger output.
+ */
+ bool Get() const;
+
+ // DigitalSource interface
+ /**
+ * @return The HAL Handle to the specified source.
+ */
+ HAL_Handle GetPortHandleForRouting() const override;
+
+ /**
+ * @return The type of analog trigger output to be used.
+ */
+ AnalogTriggerType GetAnalogTriggerTypeForRouting() const override;
+
+ /**
+ * Is source an AnalogTrigger
+ */
+ bool IsAnalogTrigger() const override;
+
+ /**
+ * @return The channel of the source.
+ */
+ int GetChannel() const override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ protected:
+ /**
+ * Create an object that represents one of the four outputs from an analog
+ * trigger.
+ *
+ * Because this class derives from DigitalSource, it can be passed into
+ * routing functions for Counter, Encoder, etc.
+ *
+ * @param trigger A pointer to the trigger for which this is an output.
+ * @param outputType An enum that specifies the output on the trigger to
+ * represent.
+ */
+ AnalogTriggerOutput(const AnalogTrigger& trigger,
+ AnalogTriggerType outputType);
+
+ private:
+ // Uses reference rather than smart pointer because a user can not construct
+ // an AnalogTriggerOutput themselves and because the AnalogTriggerOutput
+ // should always be in scope at the same time as an AnalogTrigger.
+ const AnalogTrigger& m_trigger;
+ AnalogTriggerType m_outputType;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/AnalogTriggerType.h b/wpilibc/src/main/native/include/frc/AnalogTriggerType.h
new file mode 100644
index 0000000..f15fb03
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/AnalogTriggerType.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+enum class AnalogTriggerType {
+ kInWindow = 0,
+ kState = 1,
+ kRisingPulse = 2,
+ kFallingPulse = 3
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Base.h b/wpilibc/src/main/native/include/frc/Base.h
new file mode 100644
index 0000000..1fdbe5d
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Base.h
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 5
+static_assert(0,
+ "GCC must be 5 or greater. If building for the roboRIO, please "
+ "update to the 2018 toolchains.");
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+static_assert(0, "Visual Studio 2015 or greater required.");
+#endif
+
+/** WPILib FRC namespace */
+namespace frc {
+
+// A struct to use as a deleter when a std::shared_ptr must wrap a raw pointer
+// that is being deleted by someone else.
+template <class T>
+struct NullDeleter {
+ void operator()(T*) const noexcept {};
+};
+
+} // namespace frc
+
+// For backwards compatibility
+#ifdef NO_NAMESPACED_WPILIB
+using namespace frc; // NOLINT
+#endif
diff --git a/wpilibc/src/main/native/include/frc/BuiltInAccelerometer.h b/wpilibc/src/main/native/include/frc/BuiltInAccelerometer.h
new file mode 100644
index 0000000..3c9fc4a
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/BuiltInAccelerometer.h
@@ -0,0 +1,63 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/ErrorBase.h"
+#include "frc/interfaces/Accelerometer.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * Built-in accelerometer.
+ *
+ * This class allows access to the roboRIO's internal accelerometer.
+ */
+class BuiltInAccelerometer : public ErrorBase,
+ public SendableBase,
+ public Accelerometer {
+ public:
+ /**
+ * Constructor.
+ *
+ * @param range The range the accelerometer will measure
+ */
+ explicit BuiltInAccelerometer(Range range = kRange_8G);
+
+ BuiltInAccelerometer(BuiltInAccelerometer&&) = default;
+ BuiltInAccelerometer& operator=(BuiltInAccelerometer&&) = default;
+
+ // Accelerometer interface
+ /**
+ * Set the measuring range of the accelerometer.
+ *
+ * @param range The maximum acceleration, positive or negative, that the
+ * accelerometer will measure. Not all accelerometers support all
+ * ranges.
+ */
+ void SetRange(Range range) override;
+
+ /**
+ * @return The acceleration of the roboRIO along the X axis in g-forces
+ */
+ double GetX() override;
+
+ /**
+ * @return The acceleration of the roboRIO along the Y axis in g-forces
+ */
+ double GetY() override;
+
+ /**
+ * @return The acceleration of the roboRIO along the Z axis in g-forces
+ */
+ double GetZ() override;
+
+ void InitSendable(SendableBuilder& builder) override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/CAN.h b/wpilibc/src/main/native/include/frc/CAN.h
new file mode 100644
index 0000000..4cd06e9
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/CAN.h
@@ -0,0 +1,149 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <hal/CANAPITypes.h>
+#include <wpi/ArrayRef.h>
+
+#include "frc/ErrorBase.h"
+
+namespace frc {
+struct CANData {
+ uint8_t data[8];
+ int32_t length;
+ uint64_t timestamp;
+};
+
+/**
+ * High level class for interfacing with CAN devices conforming to
+ * the standard CAN spec.
+ *
+ * No packets that can be sent gets blocked by the RoboRIO, so all methods
+ * work identically in all robot modes.
+ *
+ * All methods are thread save, however the buffer objects passed in
+ * by the user need to not be modified for the duration of their calls.
+ */
+class CAN : public ErrorBase {
+ public:
+ /**
+ * Create a new CAN communication interface with the specific device ID.
+ * This uses the team manufacturer and device types.
+ * The device ID is 6 bits (0-63)
+ *
+ * @param deviceId The device id
+ */
+ explicit CAN(int deviceId);
+
+ /**
+ * Create a new CAN communication interface with a specific device ID,
+ * manufacturer and device type. The device ID is 6 bits, the
+ * manufacturer is 8 bits, and the device type is 5 bits.
+ *
+ * @param deviceId The device ID
+ * @param deviceManufacturer The device manufacturer
+ * @param deviceType The device type
+ */
+ CAN(int deviceId, int deviceManufacturer, int deviceType);
+
+ /**
+ * Closes the CAN communication.
+ */
+ ~CAN() override;
+
+ CAN(CAN&& rhs);
+ CAN& operator=(CAN&& rhs);
+
+ /**
+ * Write a packet to the CAN device with a specific ID. This ID is 10 bits.
+ *
+ * @param data The data to write (8 bytes max)
+ * @param length The data length to write
+ * @param apiId The API ID to write.
+ */
+ void WritePacket(const uint8_t* data, int length, int apiId);
+
+ /**
+ * Write a repeating packet to the CAN device with a specific ID. This ID is
+ * 10 bits. The RoboRIO will automatically repeat the packet at the specified
+ * interval
+ *
+ * @param data The data to write (8 bytes max)
+ * @param length The data length to write
+ * @param apiId The API ID to write.
+ * @param repeatMs The period to repeat the packet at.
+ */
+ void WritePacketRepeating(const uint8_t* data, int length, int apiId,
+ int repeatMs);
+
+ /**
+ * Stop a repeating packet with a specific ID. This ID is 10 bits.
+ *
+ * @param apiId The API ID to stop repeating
+ */
+ void StopPacketRepeating(int apiId);
+
+ /**
+ * Read a new CAN packet. This will only return properly once per packet
+ * received. Multiple calls without receiving another packet will return
+ * false.
+ *
+ * @param apiId The API ID to read.
+ * @param data Storage for the received data.
+ * @return True if the data is valid, otherwise false.
+ */
+ bool ReadPacketNew(int apiId, CANData* data);
+
+ /**
+ * Read a CAN packet. The will continuously return the last packet received,
+ * without accounting for packet age.
+ *
+ * @param apiId The API ID to read.
+ * @param data Storage for the received data.
+ * @return True if the data is valid, otherwise false.
+ */
+ bool ReadPacketLatest(int apiId, CANData* data);
+
+ /**
+ * Read a CAN packet. The will return the last packet received until the
+ * packet is older then the requested timeout. Then it will return false.
+ *
+ * @param apiId The API ID to read.
+ * @param timeoutMs The timeout time for the packet
+ * @param data Storage for the received data.
+ * @return True if the data is valid, otherwise false.
+ */
+ bool ReadPacketTimeout(int apiId, int timeoutMs, CANData* data);
+
+ /**
+ * Read a CAN packet. The will return the last packet received until the
+ * packet is older then the requested timeout. Then it will return false. The
+ * period parameter is used when you know the packet is sent at specific
+ * intervals, so calls will not attempt to read a new packet from the network
+ * until that period has passed. We do not recommend users use this API unless
+ * they know the implications.
+ *
+ * @param apiId The API ID to read.
+ * @param timeoutMs The timeout time for the packet
+ * @param periodMs The usual period for the packet
+ * @param data Storage for the received data.
+ * @return True if the data is valid, otherwise false.
+ */
+ bool ReadPeriodicPacket(int apiId, int timeoutMs, int periodMs,
+ CANData* data);
+
+ static constexpr HAL_CANManufacturer kTeamManufacturer = HAL_CAN_Man_kTeamUse;
+ static constexpr HAL_CANDeviceType kTeamDeviceType =
+ HAL_CAN_Dev_kMiscellaneous;
+
+ private:
+ HAL_CANHandle m_handle = HAL_kInvalidHandle;
+};
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Compressor.h b/wpilibc/src/main/native/include/frc/Compressor.h
new file mode 100644
index 0000000..97f64d1
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Compressor.h
@@ -0,0 +1,179 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <hal/Types.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/SensorUtil.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * Class for operating a compressor connected to a %PCM (Pneumatic Control
+ * Module).
+ *
+ * The PCM will automatically run in closed loop mode by default whenever a
+ * Solenoid object is created. For most cases, a Compressor object does not need
+ * to be instantiated or used in a robot program. This class is only required in
+ * cases where the robot program needs a more detailed status of the compressor
+ * or to enable/disable closed loop control.
+ *
+ * Note: you cannot operate the compressor directly from this class as doing so
+ * would circumvent the safety provided by using the pressure switch and closed
+ * loop control. You can only turn off closed loop control, thereby stopping
+ * the compressor from operating.
+ */
+class Compressor : public ErrorBase, public SendableBase {
+ public:
+ /**
+ * Constructor. The default PCM ID is 0.
+ *
+ * @param module The PCM ID to use (0-62)
+ */
+ explicit Compressor(int pcmID = SensorUtil::GetDefaultSolenoidModule());
+
+ ~Compressor() override = default;
+
+ Compressor(Compressor&&) = default;
+ Compressor& operator=(Compressor&&) = default;
+
+ /**
+ * Starts closed-loop control. Note that closed loop control is enabled by
+ * default.
+ */
+ void Start();
+
+ /**
+ * Stops closed-loop control. Note that closed loop control is enabled by
+ * default.
+ */
+ void Stop();
+
+ /**
+ * Check if compressor output is active.
+ *
+ * @return true if the compressor is on
+ */
+ bool Enabled() const;
+
+ /**
+ * Check if the pressure switch is triggered.
+ *
+ * @return true if pressure is low
+ */
+ bool GetPressureSwitchValue() const;
+
+ /**
+ * Query how much current the compressor is drawing.
+ *
+ * @return The current through the compressor, in amps
+ */
+ double GetCompressorCurrent() const;
+
+ /**
+ * Enables or disables automatically turning the compressor on when the
+ * pressure is low.
+ *
+ * @param on Set to true to enable closed loop control of the compressor.
+ * False to disable.
+ */
+ void SetClosedLoopControl(bool on);
+
+ /**
+ * Returns true if the compressor will automatically turn on when the
+ * pressure is low.
+ *
+ * @return True if closed loop control of the compressor is enabled. False if
+ * disabled.
+ */
+ bool GetClosedLoopControl() const;
+
+ /**
+ * Query if the compressor output has been disabled due to high current draw.
+ *
+ * @return true if PCM is in fault state : Compressor Drive is
+ * disabled due to compressor current being too high.
+ */
+ bool GetCompressorCurrentTooHighFault() const;
+
+ /**
+ * Query if the compressor output has been disabled due to high current draw
+ * (sticky).
+ *
+ * A sticky fault will not clear on device reboot, it must be cleared through
+ * code or the webdash.
+ *
+ * @return true if PCM sticky fault is set : Compressor Drive is
+ * disabled due to compressor current being too high.
+ */
+ bool GetCompressorCurrentTooHighStickyFault() const;
+
+ /**
+ * Query if the compressor output has been disabled due to a short circuit
+ * (sticky).
+ *
+ * A sticky fault will not clear on device reboot, it must be cleared through
+ * code or the webdash.
+ *
+ * @return true if PCM sticky fault is set : Compressor output
+ * appears to be shorted.
+ */
+ bool GetCompressorShortedStickyFault() const;
+
+ /**
+ * Query if the compressor output has been disabled due to a short circuit.
+ *
+ * @return true if PCM is in fault state : Compressor output
+ * appears to be shorted.
+ */
+ bool GetCompressorShortedFault() const;
+
+ /**
+ * Query if the compressor output does not appear to be wired (sticky).
+ *
+ * A sticky fault will not clear on device reboot, it must be cleared through
+ * code or the webdash.
+ *
+ * @return true if PCM sticky fault is set : Compressor does not
+ * appear to be wired, i.e. compressor is not drawing enough current.
+ */
+ bool GetCompressorNotConnectedStickyFault() const;
+
+ /**
+ * Query if the compressor output does not appear to be wired.
+ *
+ * @return true if PCM is in fault state : Compressor does not
+ * appear to be wired, i.e. compressor is not drawing enough current.
+ */
+ bool GetCompressorNotConnectedFault() const;
+
+ /**
+ * Clear ALL sticky faults inside PCM that Compressor is wired to.
+ *
+ * If a sticky fault is set, then it will be persistently cleared. Compressor
+ * drive maybe momentarily disable while flags are being cleared. Care should
+ * be taken to not call this too frequently, otherwise normal compressor
+ * functionality may be prevented.
+ *
+ * If no sticky faults are set then this call will have no effect.
+ */
+ void ClearAllPCMStickyFaults();
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ protected:
+ HAL_CompressorHandle m_compressorHandle = HAL_kInvalidHandle;
+
+ private:
+ void SetCompressor(bool on);
+ int m_module;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Controller.h b/wpilibc/src/main/native/include/frc/Controller.h
new file mode 100644
index 0000000..b327723
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Controller.h
@@ -0,0 +1,39 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+/**
+ * Interface for Controllers.
+ *
+ * Common interface for controllers. Controllers run control loops, the most
+ * common are PID controllers and their variants, but this includes anything
+ * that is controlling an actuator in a separate thread.
+ */
+class Controller {
+ public:
+ Controller() = default;
+ virtual ~Controller() = default;
+
+ Controller(Controller&&) = default;
+ Controller& operator=(Controller&&) = default;
+
+ /**
+ * Allows the control loop to run
+ */
+ virtual void Enable() = 0;
+
+ /**
+ * Stops the control loop from running until explicitly re-enabled by calling
+ * enable()
+ */
+ virtual void Disable() = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/ControllerPower.h b/wpilibc/src/main/native/include/frc/ControllerPower.h
new file mode 100644
index 0000000..1359961
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/ControllerPower.h
@@ -0,0 +1,152 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/deprecated.h>
+
+namespace frc {
+
+class ControllerPower {
+ public:
+ /**
+ * Get the input voltage to the robot controller.
+ *
+ * @return The controller input voltage value in Volts
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static double GetInputVoltage();
+
+ /**
+ * Get the input current to the robot controller.
+ *
+ * @return The controller input current value in Amps
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static double GetInputCurrent();
+
+ /**
+ * Get the voltage of the 3.3V rail.
+ *
+ * @return The controller 3.3V rail voltage value in Volts
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static double GetVoltage3V3();
+
+ /**
+ * Get the current output of the 3.3V rail.
+ *
+ * @return The controller 3.3V rail output current value in Amps
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static double GetCurrent3V3();
+
+ /**
+ * Get the enabled state of the 3.3V rail. The rail may be disabled due to a
+ * controller brownout, a short circuit on the rail, or controller
+ * over-voltage.
+ *
+ * @return The controller 3.3V rail enabled value. True for enabled.
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static bool GetEnabled3V3();
+
+ /**
+ * Get the count of the total current faults on the 3.3V rail since the
+ * controller has booted.
+ *
+ * @return The number of faults
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static int GetFaultCount3V3();
+
+ /**
+ * Get the voltage of the 5V rail.
+ *
+ * @return The controller 5V rail voltage value in Volts
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static double GetVoltage5V();
+
+ /**
+ * Get the current output of the 5V rail.
+ *
+ * @return The controller 5V rail output current value in Amps
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static double GetCurrent5V();
+
+ /**
+ * Get the enabled state of the 5V rail. The rail may be disabled due to a
+ * controller brownout, a short circuit on the rail, or controller
+ * over-voltage.
+ *
+ * @return The controller 5V rail enabled value. True for enabled.
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static bool GetEnabled5V();
+
+ /**
+ * Get the count of the total current faults on the 5V rail since the
+ * controller has booted.
+ *
+ * @return The number of faults
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static int GetFaultCount5V();
+
+ /**
+ * Get the voltage of the 6V rail.
+ *
+ * @return The controller 6V rail voltage value in Volts
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static double GetVoltage6V();
+
+ /**
+ * Get the current output of the 6V rail.
+ *
+ * @return The controller 6V rail output current value in Amps
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static double GetCurrent6V();
+
+ /**
+ * Get the enabled state of the 6V rail. The rail may be disabled due to a
+ * controller brownout, a short circuit on the rail, or controller
+ * over-voltage.
+ *
+ * @return The controller 6V rail enabled value. True for enabled.
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static bool GetEnabled6V();
+
+ /**
+ * Get the count of the total current faults on the 6V rail since the
+ * controller has booted.
+ *
+ * @return The number of faults.
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ static int GetFaultCount6V();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Counter.h b/wpilibc/src/main/native/include/frc/Counter.h
new file mode 100644
index 0000000..2705a39
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Counter.h
@@ -0,0 +1,436 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <hal/Types.h>
+
+#include "frc/AnalogTrigger.h"
+#include "frc/CounterBase.h"
+#include "frc/ErrorBase.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class DigitalGlitchFilter;
+
+/**
+ * Class for counting the number of ticks on a digital input channel.
+ *
+ * This is a general purpose class for counting repetitive events. It can return
+ * the number of counts, the period of the most recent cycle, and detect when
+ * the signal being counted has stopped by supplying a maximum cycle time.
+ *
+ * All counters will immediately start counting - Reset() them if you need them
+ * to be zeroed before use.
+ */
+class Counter : public ErrorBase, public SendableBase, public CounterBase {
+ public:
+ enum Mode {
+ kTwoPulse = 0,
+ kSemiperiod = 1,
+ kPulseLength = 2,
+ kExternalDirection = 3
+ };
+
+ /**
+ * Create an instance of a counter where no sources are selected.
+ *
+ * They all must be selected by calling functions to specify the upsource and
+ * the downsource independently.
+ *
+ * This creates a ChipObject counter and initializes status variables
+ * appropriately.
+ *
+ * The counter will start counting immediately.
+ *
+ * @param mode The counter mode
+ */
+ explicit Counter(Mode mode = kTwoPulse);
+
+ /**
+ * Create an instance of a Counter object.
+ *
+ * Create an up-Counter instance given a channel.
+ *
+ * The counter will start counting immediately.
+ *
+ * @param channel The DIO channel to use as the up source. 0-9 are on-board,
+ * 10-25 are on the MXP
+ */
+ explicit Counter(int channel);
+
+ /**
+ * Create an instance of a counter from a Digital Source (such as a Digital
+ * Input).
+ *
+ * This is used if an existing digital input is to be shared by multiple other
+ * objects such as encoders or if the Digital Source is not a Digital Input
+ * channel (such as an Analog Trigger).
+ *
+ * The counter will start counting immediately.
+ * @param source A pointer to the existing DigitalSource object. It will be
+ * set as the Up Source.
+ */
+ explicit Counter(DigitalSource* source);
+
+ /**
+ * Create an instance of a counter from a Digital Source (such as a Digital
+ * Input).
+ *
+ * This is used if an existing digital input is to be shared by multiple other
+ * objects such as encoders or if the Digital Source is not a Digital Input
+ * channel (such as an Analog Trigger).
+ *
+ * The counter will start counting immediately.
+ *
+ * @param source A pointer to the existing DigitalSource object. It will be
+ * set as the Up Source.
+ */
+ explicit Counter(std::shared_ptr<DigitalSource> source);
+
+ /**
+ * Create an instance of a Counter object.
+ *
+ * Create an instance of a simple up-Counter given an analog trigger.
+ * Use the trigger state output from the analog trigger.
+ *
+ * The counter will start counting immediately.
+ *
+ * @param trigger The reference to the existing AnalogTrigger object.
+ */
+ explicit Counter(const AnalogTrigger& trigger);
+
+ /**
+ * Create an instance of a Counter object.
+ *
+ * Creates a full up-down counter given two Digital Sources.
+ *
+ * @param encodingType The quadrature decoding mode (1x or 2x)
+ * @param upSource The pointer to the DigitalSource to set as the up
+ * source
+ * @param downSource The pointer to the DigitalSource to set as the down
+ * source
+ * @param inverted True to invert the output (reverse the direction)
+ */
+ Counter(EncodingType encodingType, DigitalSource* upSource,
+ DigitalSource* downSource, bool inverted);
+
+ /**
+ * Create an instance of a Counter object.
+ *
+ * Creates a full up-down counter given two Digital Sources.
+ *
+ * @param encodingType The quadrature decoding mode (1x or 2x)
+ * @param upSource The pointer to the DigitalSource to set as the up
+ * source
+ * @param downSource The pointer to the DigitalSource to set as the down
+ * source
+ * @param inverted True to invert the output (reverse the direction)
+ */
+ Counter(EncodingType encodingType, std::shared_ptr<DigitalSource> upSource,
+ std::shared_ptr<DigitalSource> downSource, bool inverted);
+
+ ~Counter() override;
+
+ Counter(Counter&& rhs);
+ Counter& operator=(Counter&& rhs);
+
+ /**
+ * Set the upsource for the counter as a digital input channel.
+ *
+ * @param channel The DIO channel to use as the up source. 0-9 are on-board,
+ * 10-25 are on the MXP
+ */
+ void SetUpSource(int channel);
+
+ /**
+ * Set the up counting source to be an analog trigger.
+ *
+ * @param analogTrigger The analog trigger object that is used for the Up
+ * Source
+ * @param triggerType The analog trigger output that will trigger the
+ * counter.
+ */
+ void SetUpSource(AnalogTrigger* analogTrigger, AnalogTriggerType triggerType);
+
+ /**
+ * Set the up counting source to be an analog trigger.
+ *
+ * @param analogTrigger The analog trigger object that is used for the Up
+ * Source
+ * @param triggerType The analog trigger output that will trigger the
+ * counter.
+ */
+ void SetUpSource(std::shared_ptr<AnalogTrigger> analogTrigger,
+ AnalogTriggerType triggerType);
+
+ void SetUpSource(DigitalSource* source);
+
+ /**
+ * Set the source object that causes the counter to count up.
+ *
+ * Set the up counting DigitalSource.
+ *
+ * @param source Pointer to the DigitalSource object to set as the up source
+ */
+ void SetUpSource(std::shared_ptr<DigitalSource> source);
+
+ /**
+ * Set the source object that causes the counter to count up.
+ *
+ * Set the up counting DigitalSource.
+ *
+ * @param source Reference to the DigitalSource object to set as the up source
+ */
+ void SetUpSource(DigitalSource& source);
+
+ /**
+ * Set the edge sensitivity on an up counting source.
+ *
+ * Set the up source to either detect rising edges or falling edges or both.
+ *
+ * @param risingEdge True to trigger on rising edges
+ * @param fallingEdge True to trigger on falling edges
+ */
+ void SetUpSourceEdge(bool risingEdge, bool fallingEdge);
+
+ /**
+ * Disable the up counting source to the counter.
+ */
+ void ClearUpSource();
+
+ /**
+ * Set the down counting source to be a digital input channel.
+ *
+ * @param channel The DIO channel to use as the up source. 0-9 are on-board,
+ * 10-25 are on the MXP
+ */
+ void SetDownSource(int channel);
+
+ /**
+ * Set the down counting source to be an analog trigger.
+ *
+ * @param analogTrigger The analog trigger object that is used for the Down
+ * Source
+ * @param triggerType The analog trigger output that will trigger the
+ * counter.
+ */
+ void SetDownSource(AnalogTrigger* analogTrigger,
+ AnalogTriggerType triggerType);
+
+ /**
+ * Set the down counting source to be an analog trigger.
+ *
+ * @param analogTrigger The analog trigger object that is used for the Down
+ * Source
+ * @param triggerType The analog trigger output that will trigger the
+ * counter.
+ */
+ void SetDownSource(std::shared_ptr<AnalogTrigger> analogTrigger,
+ AnalogTriggerType triggerType);
+
+ /**
+ * Set the source object that causes the counter to count down.
+ *
+ * Set the down counting DigitalSource.
+ *
+ * @param source Pointer to the DigitalSource object to set as the down source
+ */
+ void SetDownSource(DigitalSource* source);
+
+ /**
+ * Set the source object that causes the counter to count down.
+ *
+ * Set the down counting DigitalSource.
+ *
+ * @param source Reference to the DigitalSource object to set as the down
+ * source
+ */
+ void SetDownSource(DigitalSource& source);
+
+ void SetDownSource(std::shared_ptr<DigitalSource> source);
+
+ /**
+ * Set the edge sensitivity on a down counting source.
+ *
+ * Set the down source to either detect rising edges or falling edges.
+ *
+ * @param risingEdge True to trigger on rising edges
+ * @param fallingEdge True to trigger on falling edges
+ */
+ void SetDownSourceEdge(bool risingEdge, bool fallingEdge);
+
+ /**
+ * Disable the down counting source to the counter.
+ */
+ void ClearDownSource();
+
+ /**
+ * Set standard up / down counting mode on this counter.
+ *
+ * Up and down counts are sourced independently from two inputs.
+ */
+ void SetUpDownCounterMode();
+
+ /**
+ * Set external direction mode on this counter.
+ *
+ * Counts are sourced on the Up counter input.
+ * The Down counter input represents the direction to count.
+ */
+ void SetExternalDirectionMode();
+
+ /**
+ * Set Semi-period mode on this counter.
+ *
+ * Counts up on both rising and falling edges.
+ */
+ void SetSemiPeriodMode(bool highSemiPeriod);
+
+ /**
+ * Configure the counter to count in up or down based on the length of the
+ * input pulse.
+ *
+ * This mode is most useful for direction sensitive gear tooth sensors.
+ *
+ * @param threshold The pulse length beyond which the counter counts the
+ * opposite direction. Units are seconds.
+ */
+ void SetPulseLengthMode(double threshold);
+
+ /**
+ * Set the Counter to return reversed sensing on the direction.
+ *
+ * This allows counters to change the direction they are counting in the case
+ * of 1X and 2X quadrature encoding only. Any other counter mode isn't
+ * supported.
+ *
+ * @param reverseDirection true if the value counted should be negated.
+ */
+ void SetReverseDirection(bool reverseDirection);
+
+ /**
+ * Set the Samples to Average which specifies the number of samples of the
+ * timer to average when calculating the period. Perform averaging to account
+ * for mechanical imperfections or as oversampling to increase resolution.
+ *
+ * @param samplesToAverage The number of samples to average from 1 to 127.
+ */
+ void SetSamplesToAverage(int samplesToAverage);
+
+ /**
+ * Get the Samples to Average which specifies the number of samples of the
+ * timer to average when calculating the period.
+ *
+ * Perform averaging to account for mechanical imperfections or as
+ * oversampling to increase resolution.
+ *
+ * @return The number of samples being averaged (from 1 to 127)
+ */
+ int GetSamplesToAverage() const;
+
+ int GetFPGAIndex() const;
+
+ // CounterBase interface
+ /**
+ * Read the current counter value.
+ *
+ * Read the value at this instant. It may still be running, so it reflects the
+ * current value. Next time it is read, it might have a different value.
+ */
+ int Get() const override;
+
+ /**
+ * Reset the Counter to zero.
+ *
+ * Set the counter value to zero. This doesn't effect the running state of the
+ * counter, just sets the current value to zero.
+ */
+ void Reset() override;
+
+ /**
+ * Get the Period of the most recent count.
+ *
+ * Returns the time interval of the most recent count. This can be used for
+ * velocity calculations to determine shaft speed.
+ *
+ * @returns The period between the last two pulses in units of seconds.
+ */
+ double GetPeriod() const override;
+
+ /**
+ * Set the maximum period where the device is still considered "moving".
+ *
+ * Sets the maximum period where the device is considered moving. This value
+ * is used to determine the "stopped" state of the counter using the
+ * GetStopped method.
+ *
+ * @param maxPeriod The maximum period where the counted device is considered
+ * moving in seconds.
+ */
+ void SetMaxPeriod(double maxPeriod) override;
+
+ /**
+ * Select whether you want to continue updating the event timer output when
+ * there are no samples captured.
+ *
+ * The output of the event timer has a buffer of periods that are averaged and
+ * posted to a register on the FPGA. When the timer detects that the event
+ * source has stopped (based on the MaxPeriod) the buffer of samples to be
+ * averaged is emptied. If you enable the update when empty, you will be
+ * notified of the stopped source and the event time will report 0 samples.
+ * If you disable update when empty, the most recent average will remain on
+ * the output until a new sample is acquired. You will never see 0 samples
+ * output (except when there have been no events since an FPGA reset) and you
+ * will likely not see the stopped bit become true (since it is updated at the
+ * end of an average and there are no samples to average).
+ *
+ * @param enabled True to enable update when empty
+ */
+ void SetUpdateWhenEmpty(bool enabled);
+
+ /**
+ * Determine if the clock is stopped.
+ *
+ * Determine if the clocked input is stopped based on the MaxPeriod value set
+ * using the SetMaxPeriod method. If the clock exceeds the MaxPeriod, then the
+ * device (and counter) are assumed to be stopped and it returns true.
+ *
+ * @return Returns true if the most recent counter period exceeds the
+ * MaxPeriod value set by SetMaxPeriod.
+ */
+ bool GetStopped() const override;
+
+ /**
+ * The last direction the counter value changed.
+ *
+ * @return The last direction the counter value changed.
+ */
+ bool GetDirection() const override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ protected:
+ // Makes the counter count up.
+ std::shared_ptr<DigitalSource> m_upSource;
+
+ // Makes the counter count down.
+ std::shared_ptr<DigitalSource> m_downSource;
+
+ // The FPGA counter object
+ HAL_CounterHandle m_counter = HAL_kInvalidHandle;
+
+ private:
+ int m_index = 0; // The index of this counter.
+
+ friend class DigitalGlitchFilter;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/CounterBase.h b/wpilibc/src/main/native/include/frc/CounterBase.h
new file mode 100644
index 0000000..7fde3ac
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/CounterBase.h
@@ -0,0 +1,39 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+/**
+ * Interface for counting the number of ticks on a digital input channel.
+ *
+ * Encoders, Gear tooth sensors, and counters should all subclass this so it can
+ * be used to build more advanced classes for control and driving.
+ *
+ * All counters will immediately start counting - Reset() them if you need them
+ * to be zeroed before use.
+ */
+class CounterBase {
+ public:
+ enum EncodingType { k1X, k2X, k4X };
+
+ CounterBase() = default;
+ virtual ~CounterBase() = default;
+
+ CounterBase(CounterBase&&) = default;
+ CounterBase& operator=(CounterBase&&) = default;
+
+ virtual int Get() const = 0;
+ virtual void Reset() = 0;
+ virtual double GetPeriod() const = 0;
+ virtual void SetMaxPeriod(double maxPeriod) = 0;
+ virtual bool GetStopped() const = 0;
+ virtual bool GetDirection() const = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/DMC60.h b/wpilibc/src/main/native/include/frc/DMC60.h
new file mode 100644
index 0000000..5a33b5a
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/DMC60.h
@@ -0,0 +1,31 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PWMSpeedController.h"
+
+namespace frc {
+
+/**
+ * Digilent DMC 60 Speed Controller.
+ */
+class DMC60 : public PWMSpeedController {
+ public:
+ /**
+ * Constructor for a Digilent DMC 60.
+ *
+ * @param channel The PWM channel that the DMC 60 is attached to. 0-9 are
+ * on-board, 10-19 are on the MXP port
+ */
+ explicit DMC60(int channel);
+
+ DMC60(DMC60&&) = default;
+ DMC60& operator=(DMC60&&) = default;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/DigitalGlitchFilter.h b/wpilibc/src/main/native/include/frc/DigitalGlitchFilter.h
new file mode 100644
index 0000000..f33955e
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/DigitalGlitchFilter.h
@@ -0,0 +1,132 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <array>
+
+#include <wpi/mutex.h>
+
+#include "frc/DigitalSource.h"
+#include "frc/ErrorBase.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class Encoder;
+class Counter;
+
+/**
+ * Class to enable glitch filtering on a set of digital inputs.
+ *
+ * This class will manage adding and removing digital inputs from a FPGA glitch
+ * filter. The filter lets the user configure the time that an input must remain
+ * high or low before it is classified as high or low.
+ */
+class DigitalGlitchFilter : public ErrorBase, public SendableBase {
+ public:
+ DigitalGlitchFilter();
+ ~DigitalGlitchFilter() override;
+
+ DigitalGlitchFilter(DigitalGlitchFilter&& rhs);
+ DigitalGlitchFilter& operator=(DigitalGlitchFilter&& rhs);
+
+ /**
+ * Assigns the DigitalSource to this glitch filter.
+ *
+ * @param input The DigitalSource to add.
+ */
+ void Add(DigitalSource* input);
+
+ /**
+ * Assigns the Encoder to this glitch filter.
+ *
+ * @param input The Encoder to add.
+ */
+ void Add(Encoder* input);
+
+ /**
+ * Assigns the Counter to this glitch filter.
+ *
+ * @param input The Counter to add.
+ */
+ void Add(Counter* input);
+
+ /**
+ * Removes a digital input from this filter.
+ *
+ * Removes the DigitalSource from this glitch filter and re-assigns it to
+ * the default filter.
+ *
+ * @param input The DigitalSource to remove.
+ */
+ void Remove(DigitalSource* input);
+
+ /**
+ * Removes an encoder from this filter.
+ *
+ * Removes the Encoder from this glitch filter and re-assigns it to
+ * the default filter.
+ *
+ * @param input The Encoder to remove.
+ */
+ void Remove(Encoder* input);
+
+ /**
+ * Removes a counter from this filter.
+ *
+ * Removes the Counter from this glitch filter and re-assigns it to
+ * the default filter.
+ *
+ * @param input The Counter to remove.
+ */
+ void Remove(Counter* input);
+
+ /**
+ * Sets the number of cycles that the input must not change state for.
+ *
+ * @param fpgaCycles The number of FPGA cycles.
+ */
+ void SetPeriodCycles(int fpgaCycles);
+
+ /**
+ * Sets the number of nanoseconds that the input must not change state for.
+ *
+ * @param nanoseconds The number of nanoseconds.
+ */
+ void SetPeriodNanoSeconds(uint64_t nanoseconds);
+
+ /**
+ * Gets the number of cycles that the input must not change state for.
+ *
+ * @return The number of cycles.
+ */
+ int GetPeriodCycles();
+
+ /**
+ * Gets the number of nanoseconds that the input must not change state for.
+ *
+ * @return The number of nanoseconds.
+ */
+ uint64_t GetPeriodNanoSeconds();
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ // Sets the filter for the input to be the requested index. A value of 0
+ // disables the filter, and the filter value must be between 1 and 3,
+ // inclusive.
+ void DoAdd(DigitalSource* input, int requested_index);
+
+ int m_channelIndex = -1;
+ static wpi::mutex m_mutex;
+ static std::array<bool, 3> m_filterAllocated;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/DigitalInput.h b/wpilibc/src/main/native/include/frc/DigitalInput.h
new file mode 100644
index 0000000..af191aa
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/DigitalInput.h
@@ -0,0 +1,78 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/DigitalSource.h"
+
+namespace frc {
+
+class DigitalGlitchFilter;
+
+/**
+ * Class to read a digital input.
+ *
+ * This class will read digital inputs and return the current value on the
+ * channel. Other devices such as encoders, gear tooth sensors, etc. that are
+ * implemented elsewhere will automatically allocate digital inputs and outputs
+ * as required. This class is only for devices like switches etc. that aren't
+ * implemented anywhere else.
+ */
+class DigitalInput : public DigitalSource {
+ public:
+ /**
+ * Create an instance of a Digital Input class.
+ *
+ * Creates a digital input given a channel.
+ *
+ * @param channel The DIO channel 0-9 are on-board, 10-25 are on the MXP port
+ */
+ explicit DigitalInput(int channel);
+
+ ~DigitalInput() override;
+
+ DigitalInput(DigitalInput&& rhs);
+ DigitalInput& operator=(DigitalInput&& rhs);
+
+ /**
+ * Get the value from a digital input channel.
+ *
+ * Retrieve the value of a single digital input channel from the FPGA.
+ */
+ bool Get() const;
+
+ // Digital Source Interface
+ /**
+ * @return The HAL Handle to the specified source.
+ */
+ HAL_Handle GetPortHandleForRouting() const override;
+
+ /**
+ * @return The type of analog trigger output to be used. 0 for Digitals
+ */
+ AnalogTriggerType GetAnalogTriggerTypeForRouting() const override;
+
+ /**
+ * Is source an AnalogTrigger
+ */
+ bool IsAnalogTrigger() const override;
+
+ /**
+ * @return The GPIO channel number that this object represents.
+ */
+ int GetChannel() const override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ int m_channel;
+ HAL_DigitalHandle m_handle = HAL_kInvalidHandle;
+
+ friend class DigitalGlitchFilter;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/DigitalOutput.h b/wpilibc/src/main/native/include/frc/DigitalOutput.h
new file mode 100644
index 0000000..49cb67d
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/DigitalOutput.h
@@ -0,0 +1,131 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <hal/Types.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * Class to write to digital outputs.
+ *
+ * Write values to the digital output channels. Other devices implemented
+ * elsewhere will allocate channels automatically so for those devices it
+ * shouldn't be done here.
+ */
+class DigitalOutput : public ErrorBase, public SendableBase {
+ public:
+ /**
+ * Create an instance of a digital output.
+ *
+ * Create a digital output given a channel.
+ *
+ * @param channel The digital channel 0-9 are on-board, 10-25 are on the MXP
+ * port
+ */
+ explicit DigitalOutput(int channel);
+
+ ~DigitalOutput() override;
+
+ DigitalOutput(DigitalOutput&& rhs);
+ DigitalOutput& operator=(DigitalOutput&& rhs);
+
+ /**
+ * Set the value of a digital output.
+ *
+ * Set the value of a digital output to either one (true) or zero (false).
+ *
+ * @param value 1 (true) for high, 0 (false) for disabled
+ */
+ void Set(bool value);
+
+ /**
+ * Gets the value being output from the Digital Output.
+ *
+ * @return the state of the digital output.
+ */
+ bool Get() const;
+
+ /**
+ * @return The GPIO channel number that this object represents.
+ */
+ int GetChannel() const;
+
+ /**
+ * Output a single pulse on the digital output line.
+ *
+ * Send a single pulse on the digital output line where the pulse duration is
+ * specified in seconds. Maximum pulse length is 0.0016 seconds.
+ *
+ * @param length The pulse length in seconds
+ */
+ void Pulse(double length);
+
+ /**
+ * Determine if the pulse is still going.
+ *
+ * Determine if a previously started pulse is still going.
+ */
+ bool IsPulsing() const;
+
+ /**
+ * Change the PWM frequency of the PWM output on a Digital Output line.
+ *
+ * The valid range is from 0.6 Hz to 19 kHz. The frequency resolution is
+ * logarithmic.
+ *
+ * There is only one PWM frequency for all digital channels.
+ *
+ * @param rate The frequency to output all digital output PWM signals.
+ */
+ void SetPWMRate(double rate);
+
+ /**
+ * Enable a PWM Output on this line.
+ *
+ * Allocate one of the 6 DO PWM generator resources from this module.
+ *
+ * Supply the initial duty-cycle to output so as to avoid a glitch when first
+ * starting.
+ *
+ * The resolution of the duty cycle is 8-bit for low frequencies (1kHz or
+ * less) but is reduced the higher the frequency of the PWM signal is.
+ *
+ * @param initialDutyCycle The duty-cycle to start generating. [0..1]
+ */
+ void EnablePWM(double initialDutyCycle);
+
+ /**
+ * Change this line from a PWM output back to a static Digital Output line.
+ *
+ * Free up one of the 6 DO PWM generator resources that were in use.
+ */
+ void DisablePWM();
+
+ /**
+ * Change the duty-cycle that is being generated on the line.
+ *
+ * The resolution of the duty cycle is 8-bit for low frequencies (1kHz or
+ * less) but is reduced the higher the frequency of the PWM signal is.
+ *
+ * @param dutyCycle The duty-cycle to change to. [0..1]
+ */
+ void UpdateDutyCycle(double dutyCycle);
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ int m_channel;
+ HAL_DigitalHandle m_handle = HAL_kInvalidHandle;
+ HAL_DigitalPWMHandle m_pwmGenerator = HAL_kInvalidHandle;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/DigitalSource.h b/wpilibc/src/main/native/include/frc/DigitalSource.h
new file mode 100644
index 0000000..5d77daa
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/DigitalSource.h
@@ -0,0 +1,37 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <hal/Types.h>
+
+#include "frc/InterruptableSensorBase.h"
+
+namespace frc {
+
+/**
+ * DigitalSource Interface.
+ *
+ * The DigitalSource represents all the possible inputs for a counter or a
+ * quadrature encoder. The source may be either a digital input or an analog
+ * input. If the caller just provides a channel, then a digital input will be
+ * constructed and freed when finished for the source. The source can either be
+ * a digital input or analog trigger but not both.
+ */
+class DigitalSource : public InterruptableSensorBase {
+ public:
+ DigitalSource() = default;
+ DigitalSource(DigitalSource&&) = default;
+ DigitalSource& operator=(DigitalSource&&) = default;
+
+ virtual HAL_Handle GetPortHandleForRouting() const = 0;
+ virtual AnalogTriggerType GetAnalogTriggerTypeForRouting() const = 0;
+ virtual bool IsAnalogTrigger() const = 0;
+ virtual int GetChannel() const = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/DoubleSolenoid.h b/wpilibc/src/main/native/include/frc/DoubleSolenoid.h
new file mode 100644
index 0000000..87c0c85
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/DoubleSolenoid.h
@@ -0,0 +1,98 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <hal/Types.h>
+
+#include "frc/SolenoidBase.h"
+
+namespace frc {
+
+/**
+ * DoubleSolenoid class for running 2 channels of high voltage Digital Output
+ * (PCM).
+ *
+ * The DoubleSolenoid class is typically used for pneumatics solenoids that
+ * have two positions controlled by two separate channels.
+ */
+class DoubleSolenoid : public SolenoidBase {
+ public:
+ enum Value { kOff, kForward, kReverse };
+
+ /**
+ * Constructor.
+ *
+ * Uses the default PCM ID of 0.
+ *
+ * @param forwardChannel The forward channel number on the PCM (0..7).
+ * @param reverseChannel The reverse channel number on the PCM (0..7).
+ */
+ explicit DoubleSolenoid(int forwardChannel, int reverseChannel);
+
+ /**
+ * Constructor.
+ *
+ * @param moduleNumber The CAN ID of the PCM.
+ * @param forwardChannel The forward channel on the PCM to control (0..7).
+ * @param reverseChannel The reverse channel on the PCM to control (0..7).
+ */
+ DoubleSolenoid(int moduleNumber, int forwardChannel, int reverseChannel);
+
+ ~DoubleSolenoid() override;
+
+ DoubleSolenoid(DoubleSolenoid&& rhs);
+ DoubleSolenoid& operator=(DoubleSolenoid&& rhs);
+
+ /**
+ * Set the value of a solenoid.
+ *
+ * @param value The value to set (Off, Forward or Reverse)
+ */
+ virtual void Set(Value value);
+
+ /**
+ * Read the current value of the solenoid.
+ *
+ * @return The current value of the solenoid.
+ */
+ virtual Value Get() const;
+
+ /**
+ * Check if the forward solenoid is blacklisted.
+ *
+ * If a solenoid is shorted, it is added to the blacklist and disabled until
+ * power cycle, or until faults are cleared.
+ *
+ * @see ClearAllPCMStickyFaults()
+ * @return If solenoid is disabled due to short.
+ */
+ bool IsFwdSolenoidBlackListed() const;
+
+ /**
+ * Check if the reverse solenoid is blacklisted.
+ *
+ * If a solenoid is shorted, it is added to the blacklist and disabled until
+ * power cycle, or until faults are cleared.
+ *
+ * @see ClearAllPCMStickyFaults()
+ * @return If solenoid is disabled due to short.
+ */
+ bool IsRevSolenoidBlackListed() const;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ int m_forwardChannel; // The forward channel on the module to control.
+ int m_reverseChannel; // The reverse channel on the module to control.
+ int m_forwardMask; // The mask for the forward channel.
+ int m_reverseMask; // The mask for the reverse channel.
+ HAL_SolenoidHandle m_forwardHandle = HAL_kInvalidHandle;
+ HAL_SolenoidHandle m_reverseHandle = HAL_kInvalidHandle;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/DriverStation.h b/wpilibc/src/main/native/include/frc/DriverStation.h
new file mode 100644
index 0000000..ddbe27a
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/DriverStation.h
@@ -0,0 +1,471 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <array>
+#include <atomic>
+#include <memory>
+#include <string>
+#include <thread>
+
+#include <hal/DriverStationTypes.h>
+#include <wpi/Twine.h>
+#include <wpi/condition_variable.h>
+#include <wpi/deprecated.h>
+#include <wpi/mutex.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/RobotState.h"
+
+namespace frc {
+
+class MatchDataSender;
+
+/**
+ * Provide access to the network communication data to / from the Driver
+ * Station.
+ */
+class DriverStation : public ErrorBase {
+ public:
+ enum Alliance { kRed, kBlue, kInvalid };
+ enum MatchType { kNone, kPractice, kQualification, kElimination };
+
+ ~DriverStation() override;
+
+ DriverStation(const DriverStation&) = delete;
+ DriverStation& operator=(const DriverStation&) = delete;
+
+ /**
+ * Return a reference to the singleton DriverStation.
+ *
+ * @return Reference to the DS instance
+ */
+ static DriverStation& GetInstance();
+
+ /**
+ * Report an error to the DriverStation messages window.
+ *
+ * The error is also printed to the program console.
+ */
+ static void ReportError(const wpi::Twine& error);
+
+ /**
+ * Report a warning to the DriverStation messages window.
+ *
+ * The warning is also printed to the program console.
+ */
+ static void ReportWarning(const wpi::Twine& error);
+
+ /**
+ * Report an error to the DriverStation messages window.
+ *
+ * The error is also printed to the program console.
+ */
+ static void ReportError(bool isError, int code, const wpi::Twine& error,
+ const wpi::Twine& location, const wpi::Twine& stack);
+
+ static constexpr int kJoystickPorts = 6;
+
+ /**
+ * The state of one joystick button. Button indexes begin at 1.
+ *
+ * @param stick The joystick to read.
+ * @param button The button index, beginning at 1.
+ * @return The state of the joystick button.
+ */
+ bool GetStickButton(int stick, int button);
+
+ /**
+ * Whether one joystick button was pressed since the last check. Button
+ * indexes begin at 1.
+ *
+ * @param stick The joystick to read.
+ * @param button The button index, beginning at 1.
+ * @return Whether the joystick button was pressed since the last check.
+ */
+ bool GetStickButtonPressed(int stick, int button);
+
+ /**
+ * Whether one joystick button was released since the last check. Button
+ * indexes begin at 1.
+ *
+ * @param stick The joystick to read.
+ * @param button The button index, beginning at 1.
+ * @return Whether the joystick button was released since the last check.
+ */
+ bool GetStickButtonReleased(int stick, int button);
+
+ /**
+ * Get the value of the axis on a joystick.
+ *
+ * This depends on the mapping of the joystick connected to the specified
+ * port.
+ *
+ * @param stick The joystick to read.
+ * @param axis The analog axis value to read from the joystick.
+ * @return The value of the axis on the joystick.
+ */
+ double GetStickAxis(int stick, int axis);
+
+ /**
+ * Get the state of a POV on the joystick.
+ *
+ * @return the angle of the POV in degrees, or -1 if the POV is not pressed.
+ */
+ int GetStickPOV(int stick, int pov);
+
+ /**
+ * The state of the buttons on the joystick.
+ *
+ * @param stick The joystick to read.
+ * @return The state of the buttons on the joystick.
+ */
+ int GetStickButtons(int stick) const;
+
+ /**
+ * Returns the number of axes on a given joystick port.
+ *
+ * @param stick The joystick port number
+ * @return The number of axes on the indicated joystick
+ */
+ int GetStickAxisCount(int stick) const;
+
+ /**
+ * Returns the number of POVs on a given joystick port.
+ *
+ * @param stick The joystick port number
+ * @return The number of POVs on the indicated joystick
+ */
+ int GetStickPOVCount(int stick) const;
+
+ /**
+ * Returns the number of buttons on a given joystick port.
+ *
+ * @param stick The joystick port number
+ * @return The number of buttons on the indicated joystick
+ */
+ int GetStickButtonCount(int stick) const;
+
+ /**
+ * Returns a boolean indicating if the controller is an xbox controller.
+ *
+ * @param stick The joystick port number
+ * @return A boolean that is true if the controller is an xbox controller.
+ */
+ bool GetJoystickIsXbox(int stick) const;
+
+ /**
+ * Returns the type of joystick at a given port.
+ *
+ * @param stick The joystick port number
+ * @return The HID type of joystick at the given port
+ */
+ int GetJoystickType(int stick) const;
+
+ /**
+ * Returns the name of the joystick at the given port.
+ *
+ * @param stick The joystick port number
+ * @return The name of the joystick at the given port
+ */
+ std::string GetJoystickName(int stick) const;
+
+ /**
+ * Returns the types of Axes on a given joystick port.
+ *
+ * @param stick The joystick port number and the target axis
+ * @return What type of axis the axis is reporting to be
+ */
+ int GetJoystickAxisType(int stick, int axis) const;
+
+ /**
+ * Check if the DS has enabled the robot.
+ *
+ * @return True if the robot is enabled and the DS is connected
+ */
+ bool IsEnabled() const;
+
+ /**
+ * Check if the robot is disabled.
+ *
+ * @return True if the robot is explicitly disabled or the DS is not connected
+ */
+ bool IsDisabled() const;
+
+ /**
+ * Check if the DS is commanding autonomous mode.
+ *
+ * @return True if the robot is being commanded to be in autonomous mode
+ */
+ bool IsAutonomous() const;
+
+ /**
+ * Check if the DS is commanding teleop mode.
+ *
+ * @return True if the robot is being commanded to be in teleop mode
+ */
+ bool IsOperatorControl() const;
+
+ /**
+ * Check if the DS is commanding test mode.
+ *
+ * @return True if the robot is being commanded to be in test mode
+ */
+ bool IsTest() const;
+
+ /**
+ * Check if the DS is attached.
+ *
+ * @return True if the DS is connected to the robot
+ */
+ bool IsDSAttached() const;
+
+ /**
+ * Has a new control packet from the driver station arrived since the last
+ * time this function was called?
+ *
+ * Warning: If you call this function from more than one place at the same
+ * time, you will not get the intended behavior.
+ *
+ * @return True if the control data has been updated since the last call.
+ */
+ bool IsNewControlData() const;
+
+ /**
+ * Is the driver station attached to a Field Management System?
+ *
+ * @return True if the robot is competing on a field being controlled by a
+ * Field Management System
+ */
+ bool IsFMSAttached() const;
+
+ /**
+ * Check if the FPGA outputs are enabled.
+ *
+ * The outputs may be disabled if the robot is disabled or e-stopped, the
+ * watchdog has expired, or if the roboRIO browns out.
+ *
+ * @return True if the FPGA outputs are enabled.
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ bool IsSysActive() const;
+
+ /**
+ * Check if the system is browned out.
+ *
+ * @return True if the system is browned out
+ * @deprecated Use RobotController static class method
+ */
+ WPI_DEPRECATED("Use RobotController static class method")
+ bool IsBrownedOut() const;
+
+ /**
+ * Returns the game specific message provided by the FMS.
+ *
+ * @return A string containing the game specific message.
+ */
+ std::string GetGameSpecificMessage() const;
+
+ /**
+ * Returns the name of the competition event provided by the FMS.
+ *
+ * @return A string containing the event name
+ */
+ std::string GetEventName() const;
+
+ /**
+ * Returns the type of match being played provided by the FMS.
+ *
+ * @return The match type enum (kNone, kPractice, kQualification,
+ * kElimination)
+ */
+ MatchType GetMatchType() const;
+
+ /**
+ * Returns the match number provided by the FMS.
+ *
+ * @return The number of the match
+ */
+ int GetMatchNumber() const;
+
+ /**
+ * Returns the number of times the current match has been replayed from the
+ * FMS.
+ *
+ * @return The number of replays
+ */
+ int GetReplayNumber() const;
+
+ /**
+ * Return the alliance that the driver station says it is on.
+ *
+ * This could return kRed or kBlue.
+ *
+ * @return The Alliance enum (kRed, kBlue or kInvalid)
+ */
+ Alliance GetAlliance() const;
+
+ /**
+ * Return the driver station location on the field.
+ *
+ * This could return 1, 2, or 3.
+ *
+ * @return The location of the driver station (1-3, 0 for invalid)
+ */
+ int GetLocation() const;
+
+ /**
+ * Wait until a new packet comes from the driver station.
+ *
+ * This blocks on a semaphore, so the waiting is efficient.
+ *
+ * This is a good way to delay processing until there is new driver station
+ * data to act on.
+ */
+ void WaitForData();
+
+ /**
+ * Wait until a new packet comes from the driver station, or wait for a
+ * timeout.
+ *
+ * If the timeout is less then or equal to 0, wait indefinitely.
+ *
+ * Timeout is in milliseconds
+ *
+ * This blocks on a semaphore, so the waiting is efficient.
+ *
+ * This is a good way to delay processing until there is new driver station
+ * data to act on.
+ *
+ * @param timeout Timeout time in seconds
+ *
+ * @return true if new data, otherwise false
+ */
+ bool WaitForData(double timeout);
+
+ /**
+ * Return the approximate match time.
+ *
+ * The FMS does not send an official match time to the robots, but does send
+ * an approximate match time. The value will count down the time remaining in
+ * the current period (auto or teleop).
+ *
+ * Warning: This is not an official time (so it cannot be used to dispute ref
+ * calls or guarantee that a function will trigger before the match ends).
+ *
+ * The Practice Match function of the DS approximates the behaviour seen on
+ * the field.
+ *
+ * @return Time remaining in current match period (auto or teleop)
+ */
+ double GetMatchTime() const;
+
+ /**
+ * Read the battery voltage.
+ *
+ * @return The battery voltage in Volts.
+ */
+ double GetBatteryVoltage() const;
+
+ /**
+ * Only to be used to tell the Driver Station what code you claim to be
+ * executing for diagnostic purposes only.
+ *
+ * @param entering If true, starting disabled code; if false, leaving disabled
+ * code.
+ */
+ void InDisabled(bool entering) { m_userInDisabled = entering; }
+
+ /**
+ * Only to be used to tell the Driver Station what code you claim to be
+ * executing for diagnostic purposes only.
+ *
+ * @param entering If true, starting autonomous code; if false, leaving
+ * autonomous code.
+ */
+ void InAutonomous(bool entering) { m_userInAutonomous = entering; }
+
+ /**
+ * Only to be used to tell the Driver Station what code you claim to be
+ * executing for diagnostic purposes only.
+ *
+ * @param entering If true, starting teleop code; if false, leaving teleop
+ * code.
+ */
+ void InOperatorControl(bool entering) { m_userInTeleop = entering; }
+
+ /**
+ * Only to be used to tell the Driver Station what code you claim to be
+ * executing for diagnostic purposes only.
+ *
+ * @param entering If true, starting test code; if false, leaving test code.
+ */
+ void InTest(bool entering) { m_userInTest = entering; }
+
+ protected:
+ /**
+ * Copy data from the DS task for the user.
+ *
+ * If no new data exists, it will just be returned, otherwise
+ * the data will be copied from the DS polling loop.
+ */
+ void GetData();
+
+ private:
+ /**
+ * DriverStation constructor.
+ *
+ * This is only called once the first time GetInstance() is called
+ */
+ DriverStation();
+
+ /**
+ * Reports errors related to unplugged joysticks.
+ *
+ * Throttles the errors so that they don't overwhelm the DS.
+ */
+ void ReportJoystickUnpluggedError(const wpi::Twine& message);
+
+ /**
+ * Reports errors related to unplugged joysticks.
+ *
+ * Throttles the errors so that they don't overwhelm the DS.
+ */
+ void ReportJoystickUnpluggedWarning(const wpi::Twine& message);
+
+ void Run();
+
+ void SendMatchData();
+
+ std::unique_ptr<MatchDataSender> m_matchDataSender;
+
+ // Joystick button rising/falling edge flags
+ wpi::mutex m_buttonEdgeMutex;
+ std::array<HAL_JoystickButtons, kJoystickPorts> m_previousButtonStates;
+ std::array<uint32_t, kJoystickPorts> m_joystickButtonsPressed;
+ std::array<uint32_t, kJoystickPorts> m_joystickButtonsReleased;
+
+ // Internal Driver Station thread
+ std::thread m_dsThread;
+ std::atomic<bool> m_isRunning{false};
+
+ wpi::mutex m_waitForDataMutex;
+ wpi::condition_variable m_waitForDataCond;
+ int m_waitForDataCounter;
+
+ // Robot state status variables
+ bool m_userInDisabled = false;
+ bool m_userInAutonomous = false;
+ bool m_userInTeleop = false;
+ bool m_userInTest = false;
+
+ double m_nextMessageTime = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Encoder.h b/wpilibc/src/main/native/include/frc/Encoder.h
new file mode 100644
index 0000000..7096eeb
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Encoder.h
@@ -0,0 +1,370 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <hal/Types.h>
+
+#include "frc/Counter.h"
+#include "frc/CounterBase.h"
+#include "frc/ErrorBase.h"
+#include "frc/PIDSource.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class DigitalSource;
+class DigitalGlitchFilter;
+
+/**
+ * Class to read quad encoders.
+ *
+ * Quadrature encoders are devices that count shaft rotation and can sense
+ * direction. The output of the QuadEncoder class is an integer that can count
+ * either up or down, and can go negative for reverse direction counting. When
+ * creating QuadEncoders, a direction is supplied that changes the sense of the
+ * output to make code more readable if the encoder is mounted such that forward
+ * movement generates negative values. Quadrature encoders have two digital
+ * outputs, an A Channel and a B Channel that are out of phase with each other
+ * to allow the FPGA to do direction sensing.
+ *
+ * All encoders will immediately start counting - Reset() them if you need them
+ * to be zeroed before use.
+ */
+class Encoder : public ErrorBase,
+ public SendableBase,
+ public CounterBase,
+ public PIDSource {
+ public:
+ enum IndexingType {
+ kResetWhileHigh,
+ kResetWhileLow,
+ kResetOnFallingEdge,
+ kResetOnRisingEdge
+ };
+
+ /**
+ * Encoder constructor.
+ *
+ * Construct a Encoder given a and b channels.
+ *
+ * The counter will start counting immediately.
+ *
+ * @param aChannel The a channel DIO channel. 0-9 are on-board, 10-25
+ * are on the MXP port
+ * @param bChannel The b channel DIO channel. 0-9 are on-board, 10-25
+ * are on the MXP port
+ * @param reverseDirection represents the orientation of the encoder and
+ * inverts the output values if necessary so forward
+ * represents positive values.
+ * @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X
+ * decoding. If 4X is selected, then an encoder FPGA
+ * object is used and the returned counts will be 4x
+ * the encoder spec'd value since all rising and
+ * falling edges are counted. If 1X or 2X are selected
+ * then a counter object will be used and the returned
+ * value will either exactly match the spec'd count or
+ * be double (2x) the spec'd count.
+ */
+ Encoder(int aChannel, int bChannel, bool reverseDirection = false,
+ EncodingType encodingType = k4X);
+
+ /**
+ * Encoder constructor.
+ *
+ * Construct a Encoder given a and b channels as digital inputs. This is used
+ * in the case where the digital inputs are shared. The Encoder class will not
+ * allocate the digital inputs and assume that they already are counted.
+ *
+ * The counter will start counting immediately.
+ *
+ * @param aSource The source that should be used for the a channel.
+ * @param bSource the source that should be used for the b channel.
+ * @param reverseDirection represents the orientation of the encoder and
+ * inverts the output values if necessary so forward
+ * represents positive values.
+ * @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X
+ * decoding. If 4X is selected, then an encoder FPGA
+ * object is used and the returned counts will be 4x
+ * the encoder spec'd value since all rising and
+ * falling edges are counted. If 1X or 2X are selected
+ * then a counter object will be used and the returned
+ * value will either exactly match the spec'd count or
+ * be double (2x) the spec'd count.
+ */
+ Encoder(DigitalSource* aSource, DigitalSource* bSource,
+ bool reverseDirection = false, EncodingType encodingType = k4X);
+
+ /**
+ * Encoder constructor.
+ *
+ * Construct a Encoder given a and b channels as digital inputs. This is used
+ * in the case where the digital inputs are shared. The Encoder class will not
+ * allocate the digital inputs and assume that they already are counted.
+ *
+ * The counter will start counting immediately.
+ *
+ * @param aSource The source that should be used for the a channel.
+ * @param bSource the source that should be used for the b channel.
+ * @param reverseDirection represents the orientation of the encoder and
+ * inverts the output values if necessary so forward
+ * represents positive values.
+ * @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X
+ * decoding. If 4X is selected, then an encoder FPGA
+ * object is used and the returned counts will be 4x
+ * the encoder spec'd value since all rising and
+ * falling edges are counted. If 1X or 2X are selected
+ * then a counter object will be used and the returned
+ * value will either exactly match the spec'd count or
+ * be double (2x) the spec'd count.
+ */
+ Encoder(DigitalSource& aSource, DigitalSource& bSource,
+ bool reverseDirection = false, EncodingType encodingType = k4X);
+
+ Encoder(std::shared_ptr<DigitalSource> aSource,
+ std::shared_ptr<DigitalSource> bSource, bool reverseDirection = false,
+ EncodingType encodingType = k4X);
+
+ ~Encoder() override;
+
+ Encoder(Encoder&& rhs);
+ Encoder& operator=(Encoder&& rhs);
+
+ // CounterBase interface
+ /**
+ * Gets the current count.
+ *
+ * Returns the current count on the Encoder. This method compensates for the
+ * decoding type.
+ *
+ * @return Current count from the Encoder adjusted for the 1x, 2x, or 4x scale
+ * factor.
+ */
+ int Get() const override;
+
+ /**
+ * Reset the Encoder distance to zero.
+ *
+ * Resets the current count to zero on the encoder.
+ */
+ void Reset() override;
+
+ /**
+ * Returns the period of the most recent pulse.
+ *
+ * Returns the period of the most recent Encoder pulse in seconds. This method
+ * compensates for the decoding type.
+ *
+ * Warning: This returns unscaled periods. Use GetRate() for rates that are
+ * scaled using the value from SetDistancePerPulse().
+ *
+ * @return Period in seconds of the most recent pulse.
+ */
+ double GetPeriod() const override;
+
+ /**
+ * Sets the maximum period for stopped detection.
+ *
+ * Sets the value that represents the maximum period of the Encoder before it
+ * will assume that the attached device is stopped. This timeout allows users
+ * to determine if the wheels or other shaft has stopped rotating.
+ * This method compensates for the decoding type.
+ *
+ * @deprecated Use SetMinRate() in favor of this method. This takes unscaled
+ * periods and SetMinRate() scales using value from
+ * SetDistancePerPulse().
+ *
+ * @param maxPeriod The maximum time between rising and falling edges before
+ * the FPGA will report the device stopped. This is expressed
+ * in seconds.
+ */
+ void SetMaxPeriod(double maxPeriod) override;
+
+ /**
+ * Determine if the encoder is stopped.
+ *
+ * Using the MaxPeriod value, a boolean is returned that is true if the
+ * encoder is considered stopped and false if it is still moving. A stopped
+ * encoder is one where the most recent pulse width exceeds the MaxPeriod.
+ *
+ * @return True if the encoder is considered stopped.
+ */
+ bool GetStopped() const override;
+
+ /**
+ * The last direction the encoder value changed.
+ *
+ * @return The last direction the encoder value changed.
+ */
+ bool GetDirection() const override;
+
+ /**
+ * Gets the raw value from the encoder.
+ *
+ * The raw value is the actual count unscaled by the 1x, 2x, or 4x scale
+ * factor.
+ *
+ * @return Current raw count from the encoder
+ */
+ int GetRaw() const;
+
+ /**
+ * The encoding scale factor 1x, 2x, or 4x, per the requested encodingType.
+ *
+ * Used to divide raw edge counts down to spec'd counts.
+ */
+ int GetEncodingScale() const;
+
+ /**
+ * Get the distance the robot has driven since the last reset.
+ *
+ * @return The distance driven since the last reset as scaled by the value
+ * from SetDistancePerPulse().
+ */
+ double GetDistance() const;
+
+ /**
+ * Get the current rate of the encoder.
+ *
+ * Units are distance per second as scaled by the value from
+ * SetDistancePerPulse().
+ *
+ * @return The current rate of the encoder.
+ */
+ double GetRate() const;
+
+ /**
+ * Set the minimum rate of the device before the hardware reports it stopped.
+ *
+ * @param minRate The minimum rate. The units are in distance per second as
+ * scaled by the value from SetDistancePerPulse().
+ */
+ void SetMinRate(double minRate);
+
+ /**
+ * Set the distance per pulse for this encoder.
+ *
+ * This sets the multiplier used to determine the distance driven based on the
+ * count value from the encoder.
+ *
+ * Do not include the decoding type in this scale. The library already
+ * compensates for the decoding type.
+ *
+ * Set this value based on the encoder's rated Pulses per Revolution and
+ * factor in gearing reductions following the encoder shaft.
+ *
+ * This distance can be in any units you like, linear or angular.
+ *
+ * @param distancePerPulse The scale factor that will be used to convert
+ * pulses to useful units.
+ */
+ void SetDistancePerPulse(double distancePerPulse);
+
+ /**
+ * Get the distance per pulse for this encoder.
+ *
+ * @return The scale factor that will be used to convert pulses to useful
+ * units.
+ */
+ double GetDistancePerPulse() const;
+
+ /**
+ * Set the direction sensing for this encoder.
+ *
+ * This sets the direction sensing on the encoder so that it could count in
+ * the correct software direction regardless of the mounting.
+ *
+ * @param reverseDirection true if the encoder direction should be reversed
+ */
+ void SetReverseDirection(bool reverseDirection);
+
+ /**
+ * Set the Samples to Average which specifies the number of samples of the
+ * timer to average when calculating the period.
+ *
+ * Perform averaging to account for mechanical imperfections or as
+ * oversampling to increase resolution.
+ *
+ * @param samplesToAverage The number of samples to average from 1 to 127.
+ */
+ void SetSamplesToAverage(int samplesToAverage);
+
+ /**
+ * Get the Samples to Average which specifies the number of samples of the
+ * timer to average when calculating the period.
+ *
+ * Perform averaging to account for mechanical imperfections or as
+ * oversampling to increase resolution.
+ *
+ * @return The number of samples being averaged (from 1 to 127)
+ */
+ int GetSamplesToAverage() const;
+
+ double PIDGet() override;
+
+ /**
+ * Set the index source for the encoder.
+ *
+ * When this source is activated, the encoder count automatically resets.
+ *
+ * @param channel A DIO channel to set as the encoder index
+ * @param type The state that will cause the encoder to reset
+ */
+ void SetIndexSource(int channel, IndexingType type = kResetOnRisingEdge);
+
+ /**
+ * Set the index source for the encoder.
+ *
+ * When this source is activated, the encoder count automatically resets.
+ *
+ * @param channel A digital source to set as the encoder index
+ * @param type The state that will cause the encoder to reset
+ */
+ void SetIndexSource(const DigitalSource& source,
+ IndexingType type = kResetOnRisingEdge);
+
+ int GetFPGAIndex() const;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ /**
+ * Common initialization code for Encoders.
+ *
+ * This code allocates resources for Encoders and is common to all
+ * constructors. The counter will start counting immediately.
+ *
+ * @param reverseDirection If true, counts down instead of up (this is all
+ * relative)
+ * @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X
+ * decoding. If 4X is selected, then an encoder FPGA
+ * object is used and the returned counts will be 4x
+ * the encoder spec'd value since all rising and
+ * falling edges are counted. If 1X or 2X are selected
+ * then a counter object will be used and the returned
+ * value will either exactly match the spec'd count or
+ * be double (2x) the spec'd count.
+ */
+ void InitEncoder(bool reverseDirection, EncodingType encodingType);
+
+ /**
+ * The scale needed to convert a raw counter value into a number of encoder
+ * pulses.
+ */
+ double DecodingScaleFactor() const;
+
+ std::shared_ptr<DigitalSource> m_aSource; // The A phase of the quad encoder
+ std::shared_ptr<DigitalSource> m_bSource; // The B phase of the quad encoder
+ std::shared_ptr<DigitalSource> m_indexSource = nullptr;
+ HAL_EncoderHandle m_encoder = HAL_kInvalidHandle;
+
+ friend class DigitalGlitchFilter;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Error.h b/wpilibc/src/main/native/include/frc/Error.h
new file mode 100644
index 0000000..8eafd10
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Error.h
@@ -0,0 +1,70 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <string>
+
+#include <wpi/StringRef.h>
+#include <wpi/Twine.h>
+
+#ifdef _WIN32
+#pragma push_macro("GetMessage")
+#undef GetMessage
+#endif
+
+#include "frc/Base.h"
+
+namespace frc {
+
+class ErrorBase;
+
+/**
+ * Error object represents a library error.
+ */
+class Error {
+ public:
+ using Code = int;
+
+ Error() = default;
+ Error(Code code, const wpi::Twine& contextMessage, wpi::StringRef filename,
+ wpi::StringRef function, int lineNumber,
+ const ErrorBase* originatingObject);
+
+ bool operator<(const Error& rhs) const;
+
+ Code GetCode() const;
+ std::string GetMessage() const;
+ std::string GetFilename() const;
+ std::string GetFunction() const;
+ int GetLineNumber() const;
+ const ErrorBase* GetOriginatingObject() const;
+ double GetTimestamp() const;
+ void Clear();
+ void Set(Code code, const wpi::Twine& contextMessage, wpi::StringRef filename,
+ wpi::StringRef function, int lineNumber,
+ const ErrorBase* originatingObject);
+
+ private:
+ void Report();
+
+ Code m_code = 0;
+ std::string m_message;
+ std::string m_filename;
+ std::string m_function;
+ int m_lineNumber = 0;
+ const ErrorBase* m_originatingObject = nullptr;
+ double m_timestamp = 0.0;
+};
+
+} // namespace frc
+
+#ifdef _WIN32
+#pragma pop_macro("GetMessage")
+#endif
diff --git a/wpilibc/src/main/native/include/frc/ErrorBase.h b/wpilibc/src/main/native/include/frc/ErrorBase.h
new file mode 100644
index 0000000..3be9765
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/ErrorBase.h
@@ -0,0 +1,202 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/StringRef.h>
+#include <wpi/Twine.h>
+#include <wpi/mutex.h>
+
+#include "frc/Base.h"
+#include "frc/Error.h"
+
+#define wpi_setErrnoErrorWithContext(context) \
+ this->SetErrnoError((context), __FILE__, __FUNCTION__, __LINE__)
+#define wpi_setErrnoError() wpi_setErrnoErrorWithContext("")
+#define wpi_setImaqErrorWithContext(code, context) \
+ do { \
+ if ((code) != 0) \
+ this->SetImaqError((code), (context), __FILE__, __FUNCTION__, __LINE__); \
+ } while (0)
+#define wpi_setErrorWithContext(code, context) \
+ do { \
+ if ((code) != 0) \
+ this->SetError((code), (context), __FILE__, __FUNCTION__, __LINE__); \
+ } while (0)
+#define wpi_setErrorWithContextRange(code, min, max, req, context) \
+ do { \
+ if ((code) != 0) \
+ this->SetErrorRange((code), (min), (max), (req), (context), __FILE__, \
+ __FUNCTION__, __LINE__); \
+ } while (0)
+#define wpi_setError(code) wpi_setErrorWithContext(code, "")
+#define wpi_setStaticErrorWithContext(object, code, context) \
+ do { \
+ if ((code) != 0) \
+ object->SetError((code), (context), __FILE__, __FUNCTION__, __LINE__); \
+ } while (0)
+#define wpi_setStaticError(object, code) \
+ wpi_setStaticErrorWithContext(object, code, "")
+#define wpi_setGlobalErrorWithContext(code, context) \
+ do { \
+ if ((code) != 0) \
+ ::frc::ErrorBase::SetGlobalError((code), (context), __FILE__, \
+ __FUNCTION__, __LINE__); \
+ } while (0)
+#define wpi_setGlobalError(code) wpi_setGlobalErrorWithContext(code, "")
+#define wpi_setWPIErrorWithContext(error, context) \
+ this->SetWPIError((wpi_error_s_##error), (wpi_error_value_##error), \
+ (context), __FILE__, __FUNCTION__, __LINE__)
+#define wpi_setWPIError(error) (wpi_setWPIErrorWithContext(error, ""))
+#define wpi_setStaticWPIErrorWithContext(object, error, context) \
+ object->SetWPIError((wpi_error_s_##error), (context), __FILE__, \
+ __FUNCTION__, __LINE__)
+#define wpi_setStaticWPIError(object, error) \
+ wpi_setStaticWPIErrorWithContext(object, error, "")
+#define wpi_setGlobalWPIErrorWithContext(error, context) \
+ ::frc::ErrorBase::SetGlobalWPIError((wpi_error_s_##error), (context), \
+ __FILE__, __FUNCTION__, __LINE__)
+#define wpi_setGlobalWPIError(error) wpi_setGlobalWPIErrorWithContext(error, "")
+
+namespace frc {
+
+/**
+ * Base class for most objects.
+ *
+ * ErrorBase is the base class for most objects since it holds the generated
+ * error for that object. In addition, there is a single instance of a global
+ * error object.
+ */
+class ErrorBase {
+ // TODO: Consider initializing instance variables and cleanup in destructor
+ public:
+ ErrorBase();
+ virtual ~ErrorBase() = default;
+
+ ErrorBase(ErrorBase&&) = default;
+ ErrorBase& operator=(ErrorBase&&) = default;
+
+ /**
+ * @brief Retrieve the current error.
+ *
+ * Get the current error information associated with this sensor.
+ */
+ virtual Error& GetError();
+
+ /**
+ * @brief Retrieve the current error.
+ *
+ * Get the current error information associated with this sensor.
+ */
+ virtual const Error& GetError() const;
+
+ /**
+ * @brief Clear the current error information associated with this sensor.
+ */
+ virtual void ClearError() const;
+
+ /**
+ * @brief Set error information associated with a C library call that set an
+ * error to the "errno" global variable.
+ *
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename Filename of the error source
+ * @param function Function of the error source
+ * @param lineNumber Line number of the error source
+ */
+ virtual void SetErrnoError(const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber) const;
+
+ /**
+ * @brief Set the current error information associated from the nivision Imaq
+ * API.
+ *
+ * @param success The return from the function
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename Filename of the error source
+ * @param function Function of the error source
+ * @param lineNumber Line number of the error source
+ */
+ virtual void SetImaqError(int success, const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber) const;
+
+ /**
+ * @brief Set the current error information associated with this sensor.
+ *
+ * @param code The error code
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename Filename of the error source
+ * @param function Function of the error source
+ * @param lineNumber Line number of the error source
+ */
+ virtual void SetError(Error::Code code, const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber) const;
+
+ /**
+ * @brief Set the current error information associated with this sensor.
+ * Range versions use for initialization code.
+ *
+ * @param code The error code
+ * @param minRange The minimum allowed allocation range
+ * @param maxRange The maximum allowed allocation range
+ * @param requestedValue The requested value to allocate
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename Filename of the error source
+ * @param function Function of the error source
+ * @param lineNumber Line number of the error source
+ */
+ virtual void SetErrorRange(Error::Code code, int32_t minRange,
+ int32_t maxRange, int32_t requestedValue,
+ const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber) const;
+
+ /**
+ * @brief Set the current error information associated with this sensor.
+ *
+ * @param errorMessage The error message from WPIErrors.h
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename Filename of the error source
+ * @param function Function of the error source
+ * @param lineNumber Line number of the error source
+ */
+ virtual void SetWPIError(const wpi::Twine& errorMessage, Error::Code code,
+ const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber) const;
+
+ virtual void CloneError(const ErrorBase& rhs) const;
+
+ /**
+ * @brief Check if the current error code represents a fatal error.
+ *
+ * @return true if the current error is fatal.
+ */
+ virtual bool StatusIsFatal() const;
+
+ static void SetGlobalError(Error::Code code, const wpi::Twine& contextMessage,
+ wpi::StringRef filename, wpi::StringRef function,
+ int lineNumber);
+
+ static void SetGlobalWPIError(const wpi::Twine& errorMessage,
+ const wpi::Twine& contextMessage,
+ wpi::StringRef filename,
+ wpi::StringRef function, int lineNumber);
+
+ /**
+ * Retrieve the current global error.
+ */
+ static const Error& GetGlobalError();
+
+ protected:
+ mutable Error m_error;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Filesystem.h b/wpilibc/src/main/native/include/frc/Filesystem.h
new file mode 100644
index 0000000..baf8044
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Filesystem.h
@@ -0,0 +1,45 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/SmallVector.h>
+
+#include "frc/RobotBase.h"
+
+namespace frc {
+namespace filesystem {
+
+/**
+ * Obtains the current working path that the program was launched with.
+ * This is analogous to the `pwd` command on unix.
+ *
+ * @param result The result of the current working path lookup.
+ */
+void GetLaunchDirectory(wpi::SmallVectorImpl<char>& result);
+
+/**
+ * Obtains the operating directory of the program. On the roboRIO, this
+ * is /home/lvuser. In simulation, it is where the simulation was launched
+ * from (`pwd`).
+ *
+ * @param result The result of the operating directory lookup.
+ */
+void GetOperatingDirectory(wpi::SmallVectorImpl<char>& result);
+
+/**
+ * Obtains the deploy directory of the program, which is the remote location
+ * src/main/deploy is deployed to by default. On the roboRIO, this is
+ * /home/lvuser/deploy. In simulation, it is where the simulation was launched
+ * from, in the subdirectory "deploy" (`pwd`/deploy).
+ *
+ * @param result The result of the operating directory lookup
+ */
+void GetDeployDirectory(wpi::SmallVectorImpl<char>& result);
+
+} // namespace filesystem
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/GamepadBase.h b/wpilibc/src/main/native/include/frc/GamepadBase.h
new file mode 100644
index 0000000..9681c84
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/GamepadBase.h
@@ -0,0 +1,32 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/deprecated.h>
+
+#include "frc/GenericHID.h"
+
+namespace frc {
+
+/**
+ * Gamepad Interface.
+ */
+class GamepadBase : public GenericHID {
+ public:
+ WPI_DEPRECATED("Inherit directly from GenericHID instead.")
+ explicit GamepadBase(int port);
+ virtual ~GamepadBase() = default;
+
+ GamepadBase(GamepadBase&&) = default;
+ GamepadBase& operator=(GamepadBase&&) = default;
+
+ virtual bool GetBumper(JoystickHand hand = kRightHand) const = 0;
+ virtual bool GetStickButton(JoystickHand hand) const = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/GearTooth.h b/wpilibc/src/main/native/include/frc/GearTooth.h
new file mode 100644
index 0000000..230f6d1
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/GearTooth.h
@@ -0,0 +1,75 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "frc/Counter.h"
+
+namespace frc {
+
+/**
+ * Alias for counter class.
+ *
+ * Implements the gear tooth sensor supplied by FIRST. Currently there is no
+ * reverse sensing on the gear tooth sensor, but in future versions we might
+ * implement the necessary timing in the FPGA to sense direction.
+ */
+class GearTooth : public Counter {
+ public:
+ // 55 uSec for threshold
+ static constexpr double kGearToothThreshold = 55e-6;
+
+ /**
+ * Construct a GearTooth sensor given a channel.
+ *
+ * @param channel The DIO channel that the sensor is connected to.
+ * 0-9 are on-board, 10-25 are on the MXP.
+ * @param directionSensitive True to enable the pulse length decoding in
+ * hardware to specify count direction.
+ */
+ explicit GearTooth(int channel, bool directionSensitive = false);
+
+ /**
+ * Construct a GearTooth sensor given a digital input.
+ *
+ * This should be used when sharing digital inputs.
+ *
+ * @param source A pointer to the existing DigitalSource object
+ * (such as a DigitalInput)
+ * @param directionSensitive True to enable the pulse length decoding in
+ * hardware to specify count direction.
+ */
+ explicit GearTooth(DigitalSource* source, bool directionSensitive = false);
+
+ /**
+ * Construct a GearTooth sensor given a digital input.
+ *
+ * This should be used when sharing digital inputs.
+ *
+ * @param source A reference to the existing DigitalSource object
+ * (such as a DigitalInput)
+ * @param directionSensitive True to enable the pulse length decoding in
+ * hardware to specify count direction.
+ */
+ explicit GearTooth(std::shared_ptr<DigitalSource> source,
+ bool directionSensitive = false);
+
+ GearTooth(GearTooth&&) = default;
+ GearTooth& operator=(GearTooth&&) = default;
+
+ /**
+ * Common code called by the constructors.
+ */
+ void EnableDirectionSensing(bool directionSensitive);
+
+ void InitSendable(SendableBuilder& builder) override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/GenericHID.h b/wpilibc/src/main/native/include/frc/GenericHID.h
new file mode 100644
index 0000000..74e5271
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/GenericHID.h
@@ -0,0 +1,189 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <string>
+
+#include "frc/ErrorBase.h"
+
+namespace frc {
+
+class DriverStation;
+
+/**
+ * GenericHID Interface.
+ */
+class GenericHID : public ErrorBase {
+ public:
+ enum RumbleType { kLeftRumble, kRightRumble };
+
+ enum HIDType {
+ kUnknown = -1,
+ kXInputUnknown = 0,
+ kXInputGamepad = 1,
+ kXInputWheel = 2,
+ kXInputArcadeStick = 3,
+ kXInputFlightStick = 4,
+ kXInputDancePad = 5,
+ kXInputGuitar = 6,
+ kXInputGuitar2 = 7,
+ kXInputDrumKit = 8,
+ kXInputGuitar3 = 11,
+ kXInputArcadePad = 19,
+ kHIDJoystick = 20,
+ kHIDGamepad = 21,
+ kHIDDriving = 22,
+ kHIDFlight = 23,
+ kHID1stPerson = 24
+ };
+
+ enum JoystickHand { kLeftHand = 0, kRightHand = 1 };
+
+ explicit GenericHID(int port);
+ virtual ~GenericHID() = default;
+
+ GenericHID(GenericHID&&) = default;
+ GenericHID& operator=(GenericHID&&) = default;
+
+ virtual double GetX(JoystickHand hand = kRightHand) const = 0;
+ virtual double GetY(JoystickHand hand = kRightHand) const = 0;
+
+ /**
+ * Get the button value (starting at button 1).
+ *
+ * The buttons are returned in a single 16 bit value with one bit representing
+ * the state of each button. The appropriate button is returned as a boolean
+ * value.
+ *
+ * @param button The button number to be read (starting at 1)
+ * @return The state of the button.
+ */
+ bool GetRawButton(int button) const;
+
+ /**
+ * Whether the button was pressed since the last check. Button indexes begin
+ * at 1.
+ *
+ * @param button The button index, beginning at 1.
+ * @return Whether the button was pressed since the last check.
+ */
+ bool GetRawButtonPressed(int button);
+
+ /**
+ * Whether the button was released since the last check. Button indexes begin
+ * at 1.
+ *
+ * @param button The button index, beginning at 1.
+ * @return Whether the button was released since the last check.
+ */
+ bool GetRawButtonReleased(int button);
+
+ /**
+ * Get the value of the axis.
+ *
+ * @param axis The axis to read, starting at 0.
+ * @return The value of the axis.
+ */
+ double GetRawAxis(int axis) const;
+
+ /**
+ * Get the angle in degrees of a POV on the HID.
+ *
+ * The POV angles start at 0 in the up direction, and increase clockwise
+ * (e.g. right is 90, upper-left is 315).
+ *
+ * @param pov The index of the POV to read (starting at 0)
+ * @return the angle of the POV in degrees, or -1 if the POV is not pressed.
+ */
+ int GetPOV(int pov = 0) const;
+
+ /**
+ * Get the number of axes for the HID.
+ *
+ * @return the number of axis for the current HID
+ */
+ int GetAxisCount() const;
+
+ /**
+ * Get the number of POVs for the HID.
+ *
+ * @return the number of POVs for the current HID
+ */
+ int GetPOVCount() const;
+
+ /**
+ * Get the number of buttons for the HID.
+ *
+ * @return the number of buttons on the current HID
+ */
+ int GetButtonCount() const;
+
+ /**
+ * Get the type of the HID.
+ *
+ * @return the type of the HID.
+ */
+ GenericHID::HIDType GetType() const;
+
+ /**
+ * Get the name of the HID.
+ *
+ * @return the name of the HID.
+ */
+ std::string GetName() const;
+
+ /**
+ * Get the axis type of a joystick axis.
+ *
+ * @return the axis type of a joystick axis.
+ */
+ int GetAxisType(int axis) const;
+
+ /**
+ * Get the port number of the HID.
+ *
+ * @return The port number of the HID.
+ */
+ int GetPort() const;
+
+ /**
+ * Set a single HID output value for the HID.
+ *
+ * @param outputNumber The index of the output to set (1-32)
+ * @param value The value to set the output to
+ */
+ void SetOutput(int outputNumber, bool value);
+
+ /**
+ * Set all output values for the HID.
+ *
+ * @param value The 32 bit output value (1 bit for each output)
+ */
+ void SetOutputs(int value);
+
+ /**
+ * Set the rumble output for the HID.
+ *
+ * The DS currently supports 2 rumble values, left rumble and right rumble.
+ *
+ * @param type Which rumble value to set
+ * @param value The normalized value (0 to 1) to set the rumble to
+ */
+ void SetRumble(RumbleType type, double value);
+
+ private:
+ DriverStation& m_ds;
+ int m_port;
+ int m_outputs = 0;
+ uint16_t m_leftRumble = 0;
+ uint16_t m_rightRumble = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/GyroBase.h b/wpilibc/src/main/native/include/frc/GyroBase.h
new file mode 100644
index 0000000..d27c7d9
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/GyroBase.h
@@ -0,0 +1,42 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/ErrorBase.h"
+#include "frc/PIDSource.h"
+#include "frc/interfaces/Gyro.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * GyroBase is the common base class for Gyro implementations such as
+ * AnalogGyro.
+ */
+class GyroBase : public Gyro,
+ public ErrorBase,
+ public SendableBase,
+ public PIDSource {
+ public:
+ GyroBase() = default;
+ GyroBase(GyroBase&&) = default;
+ GyroBase& operator=(GyroBase&&) = default;
+
+ // PIDSource interface
+ /**
+ * Get the PIDOutput for the PIDSource base object. Can be set to return
+ * angle or rate using SetPIDSourceType(). Defaults to angle.
+ *
+ * @return The PIDOutput (angle or rate, defaults to angle)
+ */
+ double PIDGet() override;
+
+ void InitSendable(SendableBuilder& builder) override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/I2C.h b/wpilibc/src/main/native/include/frc/I2C.h
new file mode 100644
index 0000000..4623c44
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/I2C.h
@@ -0,0 +1,142 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <hal/I2CTypes.h>
+
+#include "frc/ErrorBase.h"
+
+namespace frc {
+
+/**
+ * I2C bus interface class.
+ *
+ * This class is intended to be used by sensor (and other I2C device) drivers.
+ * It probably should not be used directly.
+ */
+class I2C : public ErrorBase {
+ public:
+ enum Port { kOnboard = 0, kMXP };
+
+ /**
+ * Constructor.
+ *
+ * @param port The I2C port to which the device is connected.
+ * @param deviceAddress The address of the device on the I2C bus.
+ */
+ I2C(Port port, int deviceAddress);
+
+ ~I2C() override;
+
+ I2C(I2C&& rhs);
+ I2C& operator=(I2C&& rhs);
+
+ /**
+ * Generic transaction.
+ *
+ * This is a lower-level interface to the I2C hardware giving you more control
+ * over each transaction.
+ *
+ * @param dataToSend Buffer of data to send as part of the transaction.
+ * @param sendSize Number of bytes to send as part of the transaction.
+ * @param dataReceived Buffer to read data into.
+ * @param receiveSize Number of bytes to read from the device.
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+ bool Transaction(uint8_t* dataToSend, int sendSize, uint8_t* dataReceived,
+ int receiveSize);
+
+ /**
+ * Attempt to address a device on the I2C bus.
+ *
+ * This allows you to figure out if there is a device on the I2C bus that
+ * responds to the address specified in the constructor.
+ *
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+ bool AddressOnly();
+
+ /**
+ * Execute a write transaction with the device.
+ *
+ * Write a single byte to a register on a device and wait until the
+ * transaction is complete.
+ *
+ * @param registerAddress The address of the register on the device to be
+ * written.
+ * @param data The byte to write to the register on the device.
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+ bool Write(int registerAddress, uint8_t data);
+
+ /**
+ * Execute a bulk write transaction with the device.
+ *
+ * Write multiple bytes to a device and wait until the
+ * transaction is complete.
+ *
+ * @param data The data to write to the register on the device.
+ * @param count The number of bytes to be written.
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+ bool WriteBulk(uint8_t* data, int count);
+
+ /**
+ * Execute a read transaction with the device.
+ *
+ * Read bytes from a device.
+ * Most I2C devices will auto-increment the register pointer internally
+ * allowing you to read consecutive registers on a device in a single
+ * transaction.
+ *
+ * @param registerAddress The register to read first in the transaction.
+ * @param count The number of bytes to read in the transaction.
+ * @param buffer A pointer to the array of bytes to store the data
+ * read from the device.
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+ bool Read(int registerAddress, int count, uint8_t* data);
+
+ /**
+ * Execute a read only transaction with the device.
+ *
+ * Read bytes from a device. This method does not write any data to prompt the
+ * device.
+ *
+ * @param buffer A pointer to the array of bytes to store the data read from
+ * the device.
+ * @param count The number of bytes to read in the transaction.
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+ bool ReadOnly(int count, uint8_t* buffer);
+
+ /**
+ * Verify that a device's registers contain expected values.
+ *
+ * Most devices will have a set of registers that contain a known value that
+ * can be used to identify them. This allows an I2C device driver to easily
+ * verify that the device contains the expected value.
+ *
+ * @pre The device must support and be configured to use register
+ * auto-increment.
+ *
+ * @param registerAddress The base register to start reading from the device.
+ * @param count The size of the field to be verified.
+ * @param expected A buffer containing the values expected from the
+ * device.
+ */
+ bool VerifySensor(int registerAddress, int count, const uint8_t* expected);
+
+ private:
+ HAL_I2CPort m_port = HAL_I2C_kInvalid;
+ int m_deviceAddress;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/InterruptableSensorBase.h b/wpilibc/src/main/native/include/frc/InterruptableSensorBase.h
new file mode 100644
index 0000000..7c9e364
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/InterruptableSensorBase.h
@@ -0,0 +1,127 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <hal/Interrupts.h>
+
+#include "frc/AnalogTriggerType.h"
+#include "frc/ErrorBase.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class InterruptableSensorBase : public ErrorBase, public SendableBase {
+ public:
+ enum WaitResult {
+ kTimeout = 0x0,
+ kRisingEdge = 0x1,
+ kFallingEdge = 0x100,
+ kBoth = 0x101,
+ };
+
+ InterruptableSensorBase() = default;
+
+ InterruptableSensorBase(InterruptableSensorBase&&) = default;
+ InterruptableSensorBase& operator=(InterruptableSensorBase&&) = default;
+
+ virtual HAL_Handle GetPortHandleForRouting() const = 0;
+ virtual AnalogTriggerType GetAnalogTriggerTypeForRouting() const = 0;
+
+ /**
+ * Request one of the 8 interrupts asynchronously on this digital input.
+ *
+ * Request interrupts in asynchronous mode where the user's interrupt handler
+ * will be called when the interrupt fires. Users that want control over the
+ * thread priority should use the synchronous method with their own spawned
+ * thread. The default is interrupt on rising edges only.
+ */
+ virtual void RequestInterrupts(HAL_InterruptHandlerFunction handler,
+ void* param);
+
+ /**
+ * Request one of the 8 interrupts synchronously on this digital input.
+ *
+ * Request interrupts in synchronous mode where the user program will have to
+ * explicitly wait for the interrupt to occur using WaitForInterrupt.
+ * The default is interrupt on rising edges only.
+ */
+ virtual void RequestInterrupts();
+
+ /**
+ * Cancel interrupts on this device.
+ *
+ * This deallocates all the chipobject structures and disables any interrupts.
+ */
+ virtual void CancelInterrupts();
+
+ /**
+ * In synchronous mode, wait for the defined interrupt to occur.
+ *
+ * You should <b>NOT</b> attempt to read the sensor from another thread while
+ * waiting for an interrupt. This is not threadsafe, and can cause memory
+ * corruption
+ *
+ * @param timeout Timeout in seconds
+ * @param ignorePrevious If true, ignore interrupts that happened before
+ * WaitForInterrupt was called.
+ * @return What interrupts fired
+ */
+ virtual WaitResult WaitForInterrupt(double timeout,
+ bool ignorePrevious = true);
+
+ /**
+ * Enable interrupts to occur on this input.
+ *
+ * Interrupts are disabled when the RequestInterrupt call is made. This gives
+ * time to do the setup of the other options before starting to field
+ * interrupts.
+ */
+ virtual void EnableInterrupts();
+
+ /**
+ * Disable Interrupts without without deallocating structures.
+ */
+ virtual void DisableInterrupts();
+
+ /**
+ * Return the timestamp for the rising interrupt that occurred most recently.
+ *
+ * This is in the same time domain as GetClock().
+ * The rising-edge interrupt should be enabled with
+ * {@link #DigitalInput.SetUpSourceEdge}
+ *
+ * @return Timestamp in seconds since boot.
+ */
+ virtual double ReadRisingTimestamp();
+
+ /**
+ * Return the timestamp for the falling interrupt that occurred most recently.
+ *
+ * This is in the same time domain as GetClock().
+ * The falling-edge interrupt should be enabled with
+ * {@link #DigitalInput.SetUpSourceEdge}
+ *
+ * @return Timestamp in seconds since boot.
+ */
+ virtual double ReadFallingTimestamp();
+
+ /**
+ * Set which edge to trigger interrupts on
+ *
+ * @param risingEdge true to interrupt on rising edge
+ * @param fallingEdge true to interrupt on falling edge
+ */
+ virtual void SetUpSourceEdge(bool risingEdge, bool fallingEdge);
+
+ protected:
+ HAL_InterruptHandle m_interrupt = HAL_kInvalidHandle;
+
+ void AllocateInterrupts(bool watcher);
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/IterativeRobot.h b/wpilibc/src/main/native/include/frc/IterativeRobot.h
new file mode 100644
index 0000000..8ce6356
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/IterativeRobot.h
@@ -0,0 +1,43 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/IterativeRobotBase.h"
+
+namespace frc {
+
+/**
+ * IterativeRobot implements the IterativeRobotBase robot program framework.
+ *
+ * The IterativeRobot class is intended to be subclassed by a user creating a
+ * robot program.
+ *
+ * Periodic() functions from the base class are called each time a new packet is
+ * received from the driver station.
+ */
+class IterativeRobot : public IterativeRobotBase {
+ public:
+ WPI_DEPRECATED(
+ "Use TimedRobot instead. It's a drop-in replacement that provides more "
+ "regular execution periods.")
+ IterativeRobot();
+ virtual ~IterativeRobot() = default;
+
+ IterativeRobot(IterativeRobot&&) = default;
+ IterativeRobot& operator=(IterativeRobot&&) = default;
+
+ /**
+ * Provide an alternate "main loop" via StartCompetition().
+ *
+ * This specific StartCompetition() implements "main loop" behaviour synced
+ * with the DS packets.
+ */
+ void StartCompetition() override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/IterativeRobotBase.h b/wpilibc/src/main/native/include/frc/IterativeRobotBase.h
new file mode 100644
index 0000000..6ff5816
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/IterativeRobotBase.h
@@ -0,0 +1,164 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/RobotBase.h"
+#include "frc/Watchdog.h"
+
+namespace frc {
+
+/**
+ * IterativeRobotBase implements a specific type of robot program framework,
+ * extending the RobotBase class.
+ *
+ * The IterativeRobotBase class does not implement StartCompetition(), so it
+ * should not be used by teams directly.
+ *
+ * This class provides the following functions which are called by the main
+ * loop, StartCompetition(), at the appropriate times:
+ *
+ * RobotInit() -- provide for initialization at robot power-on
+ *
+ * Init() functions -- each of the following functions is called once when the
+ * appropriate mode is entered:
+ * - DisabledInit() -- called each and every time disabled is entered from
+ * another mode
+ * - AutonomousInit() -- called each and every time autonomous is entered from
+ * another mode
+ * - TeleopInit() -- called each and every time teleop is entered from
+ * another mode
+ * - TestInit() -- called each and every time test is entered from
+ * another mode
+ *
+ * Periodic() functions -- each of these functions is called on an interval:
+ * - RobotPeriodic()
+ * - DisabledPeriodic()
+ * - AutonomousPeriodic()
+ * - TeleopPeriodic()
+ * - TestPeriodic()
+ */
+class IterativeRobotBase : public RobotBase {
+ public:
+ /**
+ * Robot-wide initialization code should go here.
+ *
+ * Users should override this method for default Robot-wide initialization
+ * which will be called when the robot is first powered on. It will be called
+ * exactly one time.
+ *
+ * Warning: the Driver Station "Robot Code" light and FMS "Robot Ready"
+ * indicators will be off until RobotInit() exits. Code in RobotInit() that
+ * waits for enable will cause the robot to never indicate that the code is
+ * ready, causing the robot to be bypassed in a match.
+ */
+ virtual void RobotInit();
+
+ /**
+ * Initialization code for disabled mode should go here.
+ *
+ * Users should override this method for initialization code which will be
+ * called each time
+ * the robot enters disabled mode.
+ */
+ virtual void DisabledInit();
+
+ /**
+ * Initialization code for autonomous mode should go here.
+ *
+ * Users should override this method for initialization code which will be
+ * called each time the robot enters autonomous mode.
+ */
+ virtual void AutonomousInit();
+
+ /**
+ * Initialization code for teleop mode should go here.
+ *
+ * Users should override this method for initialization code which will be
+ * called each time the robot enters teleop mode.
+ */
+ virtual void TeleopInit();
+
+ /**
+ * Initialization code for test mode should go here.
+ *
+ * Users should override this method for initialization code which will be
+ * called each time the robot enters test mode.
+ */
+ virtual void TestInit();
+
+ /**
+ * Periodic code for all modes should go here.
+ *
+ * This function is called each time a new packet is received from the driver
+ * station.
+ */
+ virtual void RobotPeriodic();
+
+ /**
+ * Periodic code for disabled mode should go here.
+ *
+ * Users should override this method for code which will be called each time a
+ * new packet is received from the driver station and the robot is in disabled
+ * mode.
+ */
+ virtual void DisabledPeriodic();
+
+ /**
+ * Periodic code for autonomous mode should go here.
+ *
+ * Users should override this method for code which will be called each time a
+ * new packet is received from the driver station and the robot is in
+ * autonomous mode.
+ */
+ virtual void AutonomousPeriodic();
+
+ /**
+ * Periodic code for teleop mode should go here.
+ *
+ * Users should override this method for code which will be called each time a
+ * new packet is received from the driver station and the robot is in teleop
+ * mode.
+ */
+ virtual void TeleopPeriodic();
+
+ /**
+ * Periodic code for test mode should go here.
+ *
+ * Users should override this method for code which will be called each time a
+ * new packet is received from the driver station and the robot is in test
+ * mode.
+ */
+ virtual void TestPeriodic();
+
+ protected:
+ /**
+ * Constructor for IterativeRobotBase.
+ *
+ * @param period Period in seconds.
+ */
+ explicit IterativeRobotBase(double period);
+
+ virtual ~IterativeRobotBase() = default;
+
+ IterativeRobotBase(IterativeRobotBase&&) = default;
+ IterativeRobotBase& operator=(IterativeRobotBase&&) = default;
+
+ void LoopFunc();
+
+ double m_period;
+
+ private:
+ enum class Mode { kNone, kDisabled, kAutonomous, kTeleop, kTest };
+
+ Mode m_lastMode = Mode::kNone;
+ Watchdog m_watchdog;
+
+ void PrintLoopOverrunMessage();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Jaguar.h b/wpilibc/src/main/native/include/frc/Jaguar.h
new file mode 100644
index 0000000..f22eb42
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Jaguar.h
@@ -0,0 +1,31 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PWMSpeedController.h"
+
+namespace frc {
+
+/**
+ * Luminary Micro / Vex Robotics Jaguar Speed Controller with PWM control.
+ */
+class Jaguar : public PWMSpeedController {
+ public:
+ /**
+ * Constructor for a Jaguar connected via PWM.
+ *
+ * @param channel The PWM channel that the Jaguar is attached to. 0-9 are
+ * on-board, 10-19 are on the MXP port
+ */
+ explicit Jaguar(int channel);
+
+ Jaguar(Jaguar&&) = default;
+ Jaguar& operator=(Jaguar&&) = default;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Joystick.h b/wpilibc/src/main/native/include/frc/Joystick.h
new file mode 100644
index 0000000..4c17589
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Joystick.h
@@ -0,0 +1,291 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <array>
+
+#include <wpi/deprecated.h>
+
+#include "frc/GenericHID.h"
+
+namespace frc {
+
+/**
+ * Handle input from standard Joysticks connected to the Driver Station.
+ *
+ * This class handles standard input that comes from the Driver Station. Each
+ * time a value is requested the most recent value is returned. There is a
+ * single class instance for each joystick and the mapping of ports to hardware
+ * buttons depends on the code in the Driver Station.
+ */
+class Joystick : public GenericHID {
+ public:
+ static constexpr int kDefaultXChannel = 0;
+ static constexpr int kDefaultYChannel = 1;
+ static constexpr int kDefaultZChannel = 2;
+ static constexpr int kDefaultTwistChannel = 2;
+ static constexpr int kDefaultThrottleChannel = 3;
+
+ WPI_DEPRECATED("Use kDefaultXChannel instead.")
+ static constexpr int kDefaultXAxis = 0;
+ WPI_DEPRECATED("Use kDefaultYChannel instead.")
+ static constexpr int kDefaultYAxis = 1;
+ WPI_DEPRECATED("Use kDefaultZChannel instead.")
+ static constexpr int kDefaultZAxis = 2;
+ WPI_DEPRECATED("Use kDefaultTwistChannel instead.")
+ static constexpr int kDefaultTwistAxis = 2;
+ WPI_DEPRECATED("Use kDefaultThrottleChannel instead.")
+ static constexpr int kDefaultThrottleAxis = 3;
+
+ enum AxisType { kXAxis, kYAxis, kZAxis, kTwistAxis, kThrottleAxis };
+ enum ButtonType { kTriggerButton, kTopButton };
+
+ /**
+ * Construct an instance of a joystick.
+ *
+ * The joystick index is the USB port on the Driver Station.
+ *
+ * @param port The port on the Driver Station that the joystick is plugged
+ * into (0-5).
+ */
+ explicit Joystick(int port);
+
+ virtual ~Joystick() = default;
+
+ Joystick(Joystick&&) = default;
+ Joystick& operator=(Joystick&&) = default;
+
+ /**
+ * Set the channel associated with the X axis.
+ *
+ * @param channel The channel to set the axis to.
+ */
+ void SetXChannel(int channel);
+
+ /**
+ * Set the channel associated with the Y axis.
+ *
+ * @param axis The axis to set the channel for.
+ * @param channel The channel to set the axis to.
+ */
+ void SetYChannel(int channel);
+
+ /**
+ * Set the channel associated with the Z axis.
+ *
+ * @param axis The axis to set the channel for.
+ * @param channel The channel to set the axis to.
+ */
+ void SetZChannel(int channel);
+
+ /**
+ * Set the channel associated with the twist axis.
+ *
+ * @param axis The axis to set the channel for.
+ * @param channel The channel to set the axis to.
+ */
+ void SetTwistChannel(int channel);
+
+ /**
+ * Set the channel associated with the throttle axis.
+ *
+ * @param axis The axis to set the channel for.
+ * @param channel The channel to set the axis to.
+ */
+ void SetThrottleChannel(int channel);
+
+ /**
+ * Set the channel associated with a specified axis.
+ *
+ * @param axis The axis to set the channel for.
+ * @param channel The channel to set the axis to.
+ */
+ WPI_DEPRECATED("Use the more specific axis channel setter functions.")
+ void SetAxisChannel(AxisType axis, int channel);
+
+ /**
+ * Get the channel currently associated with the X axis.
+ *
+ * @return The channel for the axis.
+ */
+ int GetXChannel() const;
+
+ /**
+ * Get the channel currently associated with the Y axis.
+ *
+ * @return The channel for the axis.
+ */
+ int GetYChannel() const;
+
+ /**
+ * Get the channel currently associated with the Z axis.
+ *
+ * @return The channel for the axis.
+ */
+ int GetZChannel() const;
+
+ /**
+ * Get the channel currently associated with the twist axis.
+ *
+ * @return The channel for the axis.
+ */
+ int GetTwistChannel() const;
+
+ /**
+ * Get the channel currently associated with the throttle axis.
+ *
+ * @return The channel for the axis.
+ */
+ int GetThrottleChannel() const;
+
+ /**
+ * Get the X value of the joystick.
+ *
+ * This depends on the mapping of the joystick connected to the current port.
+ *
+ * @param hand This parameter is ignored for the Joystick class and is only
+ * here to complete the GenericHID interface.
+ */
+ double GetX(JoystickHand hand = kRightHand) const override;
+
+ /**
+ * Get the Y value of the joystick.
+ *
+ * This depends on the mapping of the joystick connected to the current port.
+ *
+ * @param hand This parameter is ignored for the Joystick class and is only
+ * here to complete the GenericHID interface.
+ */
+ double GetY(JoystickHand hand = kRightHand) const override;
+
+ /**
+ * Get the Z value of the current joystick.
+ *
+ * This depends on the mapping of the joystick connected to the current port.
+ */
+ double GetZ() const;
+
+ /**
+ * Get the twist value of the current joystick.
+ *
+ * This depends on the mapping of the joystick connected to the current port.
+ */
+ double GetTwist() const;
+
+ /**
+ * Get the throttle value of the current joystick.
+ *
+ * This depends on the mapping of the joystick connected to the current port.
+ */
+ double GetThrottle() const;
+
+ /**
+ * For the current joystick, return the axis determined by the argument.
+ *
+ * This is for cases where the joystick axis is returned programatically,
+ * otherwise one of the previous functions would be preferable (for example
+ * GetX()).
+ *
+ * @param axis The axis to read.
+ * @return The value of the axis.
+ */
+ WPI_DEPRECATED("Use the more specific axis channel getter functions.")
+ double GetAxis(AxisType axis) const;
+
+ /**
+ * Read the state of the trigger on the joystick.
+ *
+ * Look up which button has been assigned to the trigger and read its state.
+ *
+ * @return The state of the trigger.
+ */
+ bool GetTrigger() const;
+
+ /**
+ * Whether the trigger was pressed since the last check.
+ *
+ * @return Whether the button was pressed since the last check.
+ */
+ bool GetTriggerPressed();
+
+ /**
+ * Whether the trigger was released since the last check.
+ *
+ * @return Whether the button was released since the last check.
+ */
+ bool GetTriggerReleased();
+
+ /**
+ * Read the state of the top button on the joystick.
+ *
+ * Look up which button has been assigned to the top and read its state.
+ *
+ * @return The state of the top button.
+ */
+ bool GetTop() const;
+
+ /**
+ * Whether the top button was pressed since the last check.
+ *
+ * @return Whether the button was pressed since the last check.
+ */
+ bool GetTopPressed();
+
+ /**
+ * Whether the top button was released since the last check.
+ *
+ * @return Whether the button was released since the last check.
+ */
+ bool GetTopReleased();
+
+ WPI_DEPRECATED("Use Joystick instances instead.")
+ static Joystick* GetStickForPort(int port);
+
+ /**
+ * Get buttons based on an enumerated type.
+ *
+ * The button type will be looked up in the list of buttons and then read.
+ *
+ * @param button The type of button to read.
+ * @return The state of the button.
+ */
+ WPI_DEPRECATED("Use the more specific button getter functions.")
+ bool GetButton(ButtonType button) const;
+
+ /**
+ * Get the magnitude of the direction vector formed by the joystick's
+ * current position relative to its origin.
+ *
+ * @return The magnitude of the direction vector
+ */
+ double GetMagnitude() const;
+
+ /**
+ * Get the direction of the vector formed by the joystick and its origin
+ * in radians.
+ *
+ * @return The direction of the vector in radians
+ */
+ double GetDirectionRadians() const;
+
+ /**
+ * Get the direction of the vector formed by the joystick and its origin
+ * in degrees.
+ *
+ * @return The direction of the vector in degrees
+ */
+ double GetDirectionDegrees() const;
+
+ private:
+ enum Axis { kX, kY, kZ, kTwist, kThrottle, kNumAxes };
+ enum Button { kTrigger = 1, kTop = 2 };
+
+ std::array<int, Axis::kNumAxes> m_axes;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/JoystickBase.h b/wpilibc/src/main/native/include/frc/JoystickBase.h
new file mode 100644
index 0000000..cba5a7e
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/JoystickBase.h
@@ -0,0 +1,33 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/deprecated.h>
+
+#include "frc/GenericHID.h"
+
+namespace frc {
+
+/**
+ * Joystick Interface.
+ */
+class JoystickBase : public GenericHID {
+ public:
+ WPI_DEPRECATED("Inherit directly from GenericHID instead.")
+ explicit JoystickBase(int port);
+ virtual ~JoystickBase() = default;
+
+ JoystickBase(JoystickBase&&) = default;
+ JoystickBase& operator=(JoystickBase&&) = default;
+
+ virtual double GetZ(JoystickHand hand = kRightHand) const = 0;
+ virtual double GetTwist() const = 0;
+ virtual double GetThrottle() const = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/MotorSafety.h b/wpilibc/src/main/native/include/frc/MotorSafety.h
new file mode 100644
index 0000000..afd0853
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/MotorSafety.h
@@ -0,0 +1,113 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/mutex.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/Timer.h"
+
+namespace frc {
+
+/**
+ * This base class runs a watchdog timer and calls the subclass's StopMotor()
+ * function if the timeout expires.
+ *
+ * The subclass should call Feed() whenever the motor value is updated.
+ */
+class MotorSafety : public ErrorBase {
+ public:
+ MotorSafety();
+ virtual ~MotorSafety();
+
+ MotorSafety(MotorSafety&& rhs);
+ MotorSafety& operator=(MotorSafety&& rhs);
+
+ /**
+ * Feed the motor safety object.
+ *
+ * Resets the timer on this object that is used to do the timeouts.
+ */
+ void Feed();
+
+ /**
+ * Set the expiration time for the corresponding motor safety object.
+ *
+ * @param expirationTime The timeout value in seconds.
+ */
+ void SetExpiration(double expirationTime);
+
+ /**
+ * Retrieve the timeout value for the corresponding motor safety object.
+ *
+ * @return the timeout value in seconds.
+ */
+ double GetExpiration() const;
+
+ /**
+ * Determine if the motor is still operating or has timed out.
+ *
+ * @return true if the motor is still operating normally and hasn't timed out.
+ */
+ bool IsAlive() const;
+
+ /**
+ * Enable/disable motor safety for this device.
+ *
+ * Turn on and off the motor safety option for this PWM object.
+ *
+ * @param enabled True if motor safety is enforced for this object.
+ */
+ void SetSafetyEnabled(bool enabled);
+
+ /**
+ * Return the state of the motor safety enabled flag.
+ *
+ * Return if the motor safety is currently enabled for this device.
+ *
+ * @return True if motor safety is enforced for this device.
+ */
+ bool IsSafetyEnabled() const;
+
+ /**
+ * Check if this motor has exceeded its timeout.
+ *
+ * This method is called periodically to determine if this motor has exceeded
+ * its timeout value. If it has, the stop method is called, and the motor is
+ * shut down until its value is updated again.
+ */
+ void Check();
+
+ /**
+ * Check the motors to see if any have timed out.
+ *
+ * This static method is called periodically to poll all the motors and stop
+ * any that have timed out.
+ */
+ static void CheckMotors();
+
+ virtual void StopMotor() = 0;
+ virtual void GetDescription(wpi::raw_ostream& desc) const = 0;
+
+ private:
+ static constexpr double kDefaultSafetyExpiration = 0.1;
+
+ // The expiration time for this object
+ double m_expiration = kDefaultSafetyExpiration;
+
+ // True if motor safety is enabled for this motor
+ bool m_enabled = false;
+
+ // The FPGA clock value when the motor has expired
+ double m_stopTime = Timer::GetFPGATimestamp();
+
+ mutable wpi::mutex m_thisMutex;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/NidecBrushless.h b/wpilibc/src/main/native/include/frc/NidecBrushless.h
new file mode 100644
index 0000000..1d63c31
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/NidecBrushless.h
@@ -0,0 +1,107 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <atomic>
+
+#include "frc/DigitalOutput.h"
+#include "frc/ErrorBase.h"
+#include "frc/MotorSafety.h"
+#include "frc/PWM.h"
+#include "frc/SpeedController.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * Nidec Brushless Motor.
+ */
+class NidecBrushless : public SendableBase,
+ public SpeedController,
+ public MotorSafety {
+ public:
+ /**
+ * Constructor.
+ *
+ * @param pwmChannel The PWM channel that the Nidec Brushless controller is
+ * attached to. 0-9 are on-board, 10-19 are on the MXP port.
+ * @param dioChannel The DIO channel that the Nidec Brushless controller is
+ * attached to. 0-9 are on-board, 10-25 are on the MXP port.
+ */
+ NidecBrushless(int pwmChannel, int dioChannel);
+
+ ~NidecBrushless() override = default;
+
+ NidecBrushless(NidecBrushless&&) = default;
+ NidecBrushless& operator=(NidecBrushless&&) = default;
+
+ // SpeedController interface
+ /**
+ * Set the PWM value.
+ *
+ * The PWM value is set using a range of -1.0 to 1.0, appropriately scaling
+ * the value for the FPGA.
+ *
+ * @param speed The speed value between -1.0 and 1.0 to set.
+ */
+ void Set(double speed) override;
+
+ /**
+ * Get the recently set value of the PWM.
+ *
+ * @return The most recently set value for the PWM between -1.0 and 1.0.
+ */
+ double Get() const override;
+
+ void SetInverted(bool isInverted) override;
+
+ bool GetInverted() const override;
+
+ /**
+ * Disable the motor. The Enable() function must be called to re-enable the
+ * motor.
+ */
+ void Disable() override;
+
+ /**
+ * Re-enable the motor after Disable() has been called. The Set() function
+ * must be called to set a new motor speed.
+ */
+ void Enable();
+
+ // PIDOutput interface
+ /**
+ * Write out the PID value as seen in the PIDOutput base object.
+ *
+ * @param output Write out the PWM value as was found in the PIDController
+ */
+ void PIDWrite(double output) override;
+
+ // MotorSafety interface
+ void StopMotor() override;
+ void GetDescription(wpi::raw_ostream& desc) const override;
+
+ /**
+ * Gets the channel number associated with the object.
+ *
+ * @return The channel number.
+ */
+ int GetChannel() const;
+
+ // Sendable interface
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ bool m_isInverted = false;
+ std::atomic_bool m_disabled{false};
+ DigitalOutput m_dio;
+ PWM m_pwm;
+ double m_speed = 0.0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Notifier.h b/wpilibc/src/main/native/include/frc/Notifier.h
new file mode 100644
index 0000000..47380bc
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Notifier.h
@@ -0,0 +1,123 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <atomic>
+#include <functional>
+#include <thread>
+#include <utility>
+
+#include <hal/Types.h>
+#include <wpi/mutex.h>
+
+#include "frc/ErrorBase.h"
+
+namespace frc {
+
+using TimerEventHandler = std::function<void()>;
+
+class Notifier : public ErrorBase {
+ public:
+ /**
+ * Create a Notifier for timer event notification.
+ *
+ * @param handler The handler is called at the notification time which is set
+ * using StartSingle or StartPeriodic.
+ */
+ explicit Notifier(TimerEventHandler handler);
+
+ template <typename Callable, typename Arg, typename... Args>
+ Notifier(Callable&& f, Arg&& arg, Args&&... args)
+ : Notifier(std::bind(std::forward<Callable>(f), std::forward<Arg>(arg),
+ std::forward<Args>(args)...)) {}
+
+ /**
+ * Free the resources for a timer event.
+ */
+ virtual ~Notifier();
+
+ Notifier(Notifier&& rhs);
+ Notifier& operator=(Notifier&& rhs);
+
+ /**
+ * Change the handler function.
+ *
+ * @param handler Handler
+ */
+ void SetHandler(TimerEventHandler handler);
+
+ /**
+ * Register for single event notification.
+ *
+ * A timer event is queued for a single event after the specified delay.
+ *
+ * @param delay Seconds to wait before the handler is called.
+ */
+ void StartSingle(double delay);
+
+ /**
+ * Register for periodic event notification.
+ *
+ * A timer event is queued for periodic event notification. Each time the
+ * interrupt occurs, the event will be immediately requeued for the same time
+ * interval.
+ *
+ * @param period Period in seconds to call the handler starting one period
+ * after the call to this method.
+ */
+ void StartPeriodic(double period);
+
+ /**
+ * Stop timer events from occuring.
+ *
+ * Stop any repeating timer events from occuring. This will also remove any
+ * single notification events from the queue.
+ *
+ * If a timer-based call to the registered handler is in progress, this
+ * function will block until the handler call is complete.
+ */
+ void Stop();
+
+ private:
+ /**
+ * Update the HAL alarm time.
+ *
+ * @param triggerTime the time at which the next alarm will be triggered
+ */
+ void UpdateAlarm(uint64_t triggerTime);
+
+ /**
+ * Update the HAL alarm time based on m_expirationTime.
+ */
+ void UpdateAlarm();
+
+ // The thread waiting on the HAL alarm
+ std::thread m_thread;
+
+ // Held while updating process information
+ wpi::mutex m_processMutex;
+
+ // HAL handle, atomic for proper destruction
+ std::atomic<HAL_NotifierHandle> m_notifier{0};
+
+ // Address of the handler
+ TimerEventHandler m_handler;
+
+ // The absolute expiration time
+ double m_expirationTime = 0;
+
+ // The relative time (either periodic or single)
+ double m_period = 0;
+
+ // True if this is a periodic event
+ bool m_periodic = false;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/PIDBase.h b/wpilibc/src/main/native/include/frc/PIDBase.h
new file mode 100644
index 0000000..f29b56e
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/PIDBase.h
@@ -0,0 +1,404 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include <wpi/deprecated.h>
+#include <wpi/mutex.h>
+
+#include "frc/Base.h"
+#include "frc/PIDInterface.h"
+#include "frc/PIDOutput.h"
+#include "frc/PIDSource.h"
+#include "frc/Timer.h"
+#include "frc/filters/LinearDigitalFilter.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * Class implements a PID Control Loop.
+ *
+ * Creates a separate thread which reads the given PIDSource and takes care of
+ * the integral calculations, as well as writing the given PIDOutput.
+ *
+ * This feedback controller runs in discrete time, so time deltas are not used
+ * in the integral and derivative calculations. Therefore, the sample rate
+ * affects the controller's behavior for a given set of PID constants.
+ */
+class PIDBase : public SendableBase, public PIDInterface, public PIDOutput {
+ public:
+ /**
+ * Allocate a PID object with the given constants for P, I, D.
+ *
+ * @param Kp the proportional coefficient
+ * @param Ki the integral coefficient
+ * @param Kd the derivative coefficient
+ * @param source The PIDSource object that is used to get values
+ * @param output The PIDOutput object that is set to the output value
+ */
+ PIDBase(double p, double i, double d, PIDSource& source, PIDOutput& output);
+
+ /**
+ * Allocate a PID object with the given constants for P, I, D.
+ *
+ * @param Kp the proportional coefficient
+ * @param Ki the integral coefficient
+ * @param Kd the derivative coefficient
+ * @param source The PIDSource object that is used to get values
+ * @param output The PIDOutput object that is set to the output value
+ */
+ PIDBase(double p, double i, double d, double f, PIDSource& source,
+ PIDOutput& output);
+
+ ~PIDBase() override = default;
+
+ PIDBase(PIDBase&&) = default;
+ PIDBase& operator=(PIDBase&&) = default;
+
+ /**
+ * Return the current PID result.
+ *
+ * This is always centered on zero and constrained the the max and min outs.
+ *
+ * @return the latest calculated output
+ */
+ virtual double Get() const;
+
+ /**
+ * Set the PID controller to consider the input to be continuous,
+ *
+ * Rather then using the max and min input range as constraints, it considers
+ * them to be the same point and automatically calculates the shortest route
+ * to the setpoint.
+ *
+ * @param continuous true turns on continuous, false turns off continuous
+ */
+ virtual void SetContinuous(bool continuous = true);
+
+ /**
+ * Sets the maximum and minimum values expected from the input.
+ *
+ * @param minimumInput the minimum value expected from the input
+ * @param maximumInput the maximum value expected from the output
+ */
+ virtual void SetInputRange(double minimumInput, double maximumInput);
+
+ /**
+ * Sets the minimum and maximum values to write.
+ *
+ * @param minimumOutput the minimum value to write to the output
+ * @param maximumOutput the maximum value to write to the output
+ */
+ virtual void SetOutputRange(double minimumOutput, double maximumOutput);
+
+ /**
+ * Set the PID Controller gain parameters.
+ *
+ * Set the proportional, integral, and differential coefficients.
+ *
+ * @param p Proportional coefficient
+ * @param i Integral coefficient
+ * @param d Differential coefficient
+ */
+ void SetPID(double p, double i, double d) override;
+
+ /**
+ * Set the PID Controller gain parameters.
+ *
+ * Set the proportional, integral, and differential coefficients.
+ *
+ * @param p Proportional coefficient
+ * @param i Integral coefficient
+ * @param d Differential coefficient
+ * @param f Feed forward coefficient
+ */
+ virtual void SetPID(double p, double i, double d, double f);
+
+ /**
+ * Set the Proportional coefficient of the PID controller gain.
+ *
+ * @param p proportional coefficient
+ */
+ void SetP(double p);
+
+ /**
+ * Set the Integral coefficient of the PID controller gain.
+ *
+ * @param i integral coefficient
+ */
+ void SetI(double i);
+
+ /**
+ * Set the Differential coefficient of the PID controller gain.
+ *
+ * @param d differential coefficient
+ */
+ void SetD(double d);
+
+ /**
+ * Get the Feed forward coefficient of the PID controller gain.
+ *
+ * @param f Feed forward coefficient
+ */
+ void SetF(double f);
+
+ /**
+ * Get the Proportional coefficient.
+ *
+ * @return proportional coefficient
+ */
+ double GetP() const override;
+
+ /**
+ * Get the Integral coefficient.
+ *
+ * @return integral coefficient
+ */
+ double GetI() const override;
+
+ /**
+ * Get the Differential coefficient.
+ *
+ * @return differential coefficient
+ */
+ double GetD() const override;
+
+ /**
+ * Get the Feed forward coefficient.
+ *
+ * @return Feed forward coefficient
+ */
+ virtual double GetF() const;
+
+ /**
+ * Set the setpoint for the PIDBase.
+ *
+ * @param setpoint the desired setpoint
+ */
+ void SetSetpoint(double setpoint) override;
+
+ /**
+ * Returns the current setpoint of the PIDBase.
+ *
+ * @return the current setpoint
+ */
+ double GetSetpoint() const override;
+
+ /**
+ * Returns the change in setpoint over time of the PIDBase.
+ *
+ * @return the change in setpoint over time
+ */
+ double GetDeltaSetpoint() const;
+
+ /**
+ * Returns the current difference of the input from the setpoint.
+ *
+ * @return the current error
+ */
+ virtual double GetError() const;
+
+ /**
+ * Returns the current average of the error over the past few iterations.
+ *
+ * You can specify the number of iterations to average with
+ * SetToleranceBuffer() (defaults to 1). This is the same value that is used
+ * for OnTarget().
+ *
+ * @return the average error
+ */
+ WPI_DEPRECATED("Use a LinearDigitalFilter as the input and GetError().")
+ virtual double GetAvgError() const;
+
+ /**
+ * Sets what type of input the PID controller will use.
+ */
+ virtual void SetPIDSourceType(PIDSourceType pidSource);
+
+ /**
+ * Returns the type of input the PID controller is using.
+ *
+ * @return the PID controller input type
+ */
+ virtual PIDSourceType GetPIDSourceType() const;
+
+ /**
+ * Set the percentage error which is considered tolerable for use with
+ * OnTarget.
+ *
+ * @param percentage error which is tolerable
+ */
+ WPI_DEPRECATED("Use SetPercentTolerance() instead.")
+ virtual void SetTolerance(double percent);
+
+ /**
+ * Set the absolute error which is considered tolerable for use with
+ * OnTarget.
+ *
+ * @param percentage error which is tolerable
+ */
+ virtual void SetAbsoluteTolerance(double absValue);
+
+ /**
+ * Set the percentage error which is considered tolerable for use with
+ * OnTarget.
+ *
+ * @param percentage error which is tolerable
+ */
+ virtual void SetPercentTolerance(double percentValue);
+
+ /**
+ * Set the number of previous error samples to average for tolerancing. When
+ * determining whether a mechanism is on target, the user may want to use a
+ * rolling average of previous measurements instead of a precise position or
+ * velocity. This is useful for noisy sensors which return a few erroneous
+ * measurements when the mechanism is on target. However, the mechanism will
+ * not register as on target for at least the specified bufLength cycles.
+ *
+ * @param bufLength Number of previous cycles to average. Defaults to 1.
+ */
+ WPI_DEPRECATED("Use a LinearDigitalFilter as the input.")
+ virtual void SetToleranceBuffer(int buf = 1);
+
+ /**
+ * Return true if the error is within the percentage of the total input range,
+ * determined by SetTolerance. This asssumes that the maximum and minimum
+ * input were set using SetInput.
+ *
+ * Currently this just reports on target as the actual value passes through
+ * the setpoint. Ideally it should be based on being within the tolerance for
+ * some period of time.
+ *
+ * This will return false until at least one input value has been computed.
+ */
+ virtual bool OnTarget() const;
+
+ /**
+ * Reset the previous error, the integral term, and disable the controller.
+ */
+ void Reset() override;
+
+ /**
+ * Passes the output directly to SetSetpoint().
+ *
+ * PIDControllers can be nested by passing a PIDController as another
+ * PIDController's output. In that case, the output of the parent controller
+ * becomes the input (i.e., the reference) of the child.
+ *
+ * It is the caller's responsibility to put the data into a valid form for
+ * SetSetpoint().
+ */
+ void PIDWrite(double output) override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ protected:
+ // Is the pid controller enabled
+ bool m_enabled = false;
+
+ mutable wpi::mutex m_thisMutex;
+
+ // Ensures when Disable() is called, PIDWrite() won't run if Calculate()
+ // is already running at that time.
+ mutable wpi::mutex m_pidWriteMutex;
+
+ PIDSource* m_pidInput;
+ PIDOutput* m_pidOutput;
+ Timer m_setpointTimer;
+
+ /**
+ * Read the input, calculate the output accordingly, and write to the output.
+ * This should only be called by the Notifier.
+ */
+ virtual void Calculate();
+
+ /**
+ * Calculate the feed forward term.
+ *
+ * Both of the provided feed forward calculations are velocity feed forwards.
+ * If a different feed forward calculation is desired, the user can override
+ * this function and provide his or her own. This function does no
+ * synchronization because the PIDBase class only calls it in synchronized
+ * code, so be careful if calling it oneself.
+ *
+ * If a velocity PID controller is being used, the F term should be set to 1
+ * over the maximum setpoint for the output. If a position PID controller is
+ * being used, the F term should be set to 1 over the maximum speed for the
+ * output measured in setpoint units per this controller's update period (see
+ * the default period in this class's constructor).
+ */
+ virtual double CalculateFeedForward();
+
+ /**
+ * Wraps error around for continuous inputs. The original error is returned if
+ * continuous mode is disabled. This is an unsynchronized function.
+ *
+ * @param error The current error of the PID controller.
+ * @return Error for continuous inputs.
+ */
+ double GetContinuousError(double error) const;
+
+ private:
+ // Factor for "proportional" control
+ double m_P;
+
+ // Factor for "integral" control
+ double m_I;
+
+ // Factor for "derivative" control
+ double m_D;
+
+ // Factor for "feed forward" control
+ double m_F;
+
+ // |maximum output|
+ double m_maximumOutput = 1.0;
+
+ // |minimum output|
+ double m_minimumOutput = -1.0;
+
+ // Maximum input - limit setpoint to this
+ double m_maximumInput = 0;
+
+ // Minimum input - limit setpoint to this
+ double m_minimumInput = 0;
+
+ // input range - difference between maximum and minimum
+ double m_inputRange = 0;
+
+ // Do the endpoints wrap around? eg. Absolute encoder
+ bool m_continuous = false;
+
+ // The prior error (used to compute velocity)
+ double m_prevError = 0;
+
+ // The sum of the errors for use in the integral calc
+ double m_totalError = 0;
+
+ enum {
+ kAbsoluteTolerance,
+ kPercentTolerance,
+ kNoTolerance
+ } m_toleranceType = kNoTolerance;
+
+ // The percetage or absolute error that is considered on target.
+ double m_tolerance = 0.05;
+
+ double m_setpoint = 0;
+ double m_prevSetpoint = 0;
+ double m_error = 0;
+ double m_result = 0;
+
+ std::shared_ptr<PIDSource> m_origSource;
+ LinearDigitalFilter m_filter{nullptr, {}, {}};
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/PIDController.h b/wpilibc/src/main/native/include/frc/PIDController.h
new file mode 100644
index 0000000..e9eea8b
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/PIDController.h
@@ -0,0 +1,137 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include <wpi/deprecated.h>
+#include <wpi/mutex.h>
+
+#include "frc/Base.h"
+#include "frc/Controller.h"
+#include "frc/Notifier.h"
+#include "frc/PIDBase.h"
+#include "frc/PIDSource.h"
+#include "frc/Timer.h"
+#include "frc/filters/LinearDigitalFilter.h"
+
+namespace frc {
+
+class PIDOutput;
+
+/**
+ * Class implements a PID Control Loop.
+ *
+ * Creates a separate thread which reads the given PIDSource and takes care of
+ * the integral calculations, as well as writing the given PIDOutput.
+ *
+ * This feedback controller runs in discrete time, so time deltas are not used
+ * in the integral and derivative calculations. Therefore, the sample rate
+ * affects the controller's behavior for a given set of PID constants.
+ */
+class PIDController : public PIDBase, public Controller {
+ public:
+ /**
+ * Allocate a PID object with the given constants for P, I, D.
+ *
+ * @param Kp the proportional coefficient
+ * @param Ki the integral coefficient
+ * @param Kd the derivative coefficient
+ * @param source The PIDSource object that is used to get values
+ * @param output The PIDOutput object that is set to the output value
+ * @param period the loop time for doing calculations in seconds. This
+ * particularly affects calculations of the integral and
+ * differental terms. The default is 0.05 (50ms).
+ */
+ PIDController(double p, double i, double d, PIDSource* source,
+ PIDOutput* output, double period = 0.05);
+
+ /**
+ * Allocate a PID object with the given constants for P, I, D.
+ *
+ * @param Kp the proportional coefficient
+ * @param Ki the integral coefficient
+ * @param Kd the derivative coefficient
+ * @param source The PIDSource object that is used to get values
+ * @param output The PIDOutput object that is set to the output value
+ * @param period the loop time for doing calculations in seconds. This
+ * particularly affects calculations of the integral and
+ * differental terms. The default is 0.05 (50ms).
+ */
+ PIDController(double p, double i, double d, double f, PIDSource* source,
+ PIDOutput* output, double period = 0.05);
+
+ /**
+ * Allocate a PID object with the given constants for P, I, D.
+ *
+ * @param Kp the proportional coefficient
+ * @param Ki the integral coefficient
+ * @param Kd the derivative coefficient
+ * @param source The PIDSource object that is used to get values
+ * @param output The PIDOutput object that is set to the output value
+ * @param period the loop time for doing calculations in seconds. This
+ * particularly affects calculations of the integral and
+ * differental terms. The default is 0.05 (50ms).
+ */
+ PIDController(double p, double i, double d, PIDSource& source,
+ PIDOutput& output, double period = 0.05);
+
+ /**
+ * Allocate a PID object with the given constants for P, I, D.
+ *
+ * @param Kp the proportional coefficient
+ * @param Ki the integral coefficient
+ * @param Kd the derivative coefficient
+ * @param source The PIDSource object that is used to get values
+ * @param output The PIDOutput object that is set to the output value
+ * @param period the loop time for doing calculations in seconds. This
+ * particularly affects calculations of the integral and
+ * differental terms. The default is 0.05 (50ms).
+ */
+ PIDController(double p, double i, double d, double f, PIDSource& source,
+ PIDOutput& output, double period = 0.05);
+
+ ~PIDController() override;
+
+ PIDController(PIDController&&) = default;
+ PIDController& operator=(PIDController&&) = default;
+
+ /**
+ * Begin running the PIDController.
+ */
+ void Enable() override;
+
+ /**
+ * Stop running the PIDController, this sets the output to zero before
+ * stopping.
+ */
+ void Disable() override;
+
+ /**
+ * Set the enabled state of the PIDController.
+ */
+ void SetEnabled(bool enable);
+
+ /**
+ * Return true if PIDController is enabled.
+ */
+ bool IsEnabled() const;
+
+ /**
+ * Reset the previous error, the integral term, and disable the controller.
+ */
+ void Reset() override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ std::unique_ptr<Notifier> m_controlLoop;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/PIDInterface.h b/wpilibc/src/main/native/include/frc/PIDInterface.h
new file mode 100644
index 0000000..72d8beb
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/PIDInterface.h
@@ -0,0 +1,29 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+class PIDInterface {
+ public:
+ PIDInterface() = default;
+ PIDInterface(PIDInterface&&) = default;
+ PIDInterface& operator=(PIDInterface&&) = default;
+
+ virtual void SetPID(double p, double i, double d) = 0;
+ virtual double GetP() const = 0;
+ virtual double GetI() const = 0;
+ virtual double GetD() const = 0;
+
+ virtual void SetSetpoint(double setpoint) = 0;
+ virtual double GetSetpoint() const = 0;
+
+ virtual void Reset() = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/PIDOutput.h b/wpilibc/src/main/native/include/frc/PIDOutput.h
new file mode 100644
index 0000000..37fb2a1
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/PIDOutput.h
@@ -0,0 +1,25 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/Base.h"
+
+namespace frc {
+
+/**
+ * PIDOutput interface is a generic output for the PID class.
+ *
+ * PWMs use this class. Users implement this interface to allow for a
+ * PIDController to read directly from the inputs.
+ */
+class PIDOutput {
+ public:
+ virtual void PIDWrite(double output) = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/PIDSource.h b/wpilibc/src/main/native/include/frc/PIDSource.h
new file mode 100644
index 0000000..1a807b1
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/PIDSource.h
@@ -0,0 +1,39 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+enum class PIDSourceType { kDisplacement, kRate };
+
+/**
+ * PIDSource interface is a generic sensor source for the PID class.
+ *
+ * All sensors that can be used with the PID class will implement the PIDSource
+ * that returns a standard value that will be used in the PID code.
+ */
+class PIDSource {
+ public:
+ virtual ~PIDSource() = default;
+
+ /**
+ * Set which parameter you are using as a process control variable.
+ *
+ * @param pidSource An enum to select the parameter.
+ */
+ virtual void SetPIDSourceType(PIDSourceType pidSource);
+
+ virtual PIDSourceType GetPIDSourceType() const;
+
+ virtual double PIDGet() = 0;
+
+ protected:
+ PIDSourceType m_pidSource = PIDSourceType::kDisplacement;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/PWM.h b/wpilibc/src/main/native/include/frc/PWM.h
new file mode 100644
index 0000000..99f213e
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/PWM.h
@@ -0,0 +1,237 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <hal/Types.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/MotorSafety.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * Class implements the PWM generation in the FPGA.
+ *
+ * The values supplied as arguments for PWM outputs range from -1.0 to 1.0. They
+ * are mapped to the hardware dependent values, in this case 0-2000 for the
+ * FPGA. Changes are immediately sent to the FPGA, and the update occurs at the
+ * next FPGA cycle (5.005ms). There is no delay.
+ *
+ * As of revision 0.1.10 of the FPGA, the FPGA interprets the 0-2000 values as
+ * follows:
+ * - 2000 = maximum pulse width
+ * - 1999 to 1001 = linear scaling from "full forward" to "center"
+ * - 1000 = center value
+ * - 999 to 2 = linear scaling from "center" to "full reverse"
+ * - 1 = minimum pulse width (currently .5ms)
+ * - 0 = disabled (i.e. PWM output is held low)
+ */
+class PWM : public MotorSafety, public SendableBase {
+ public:
+ /**
+ * Represents the amount to multiply the minimum servo-pulse pwm period by.
+ */
+ enum PeriodMultiplier {
+ /**
+ * Don't skip pulses. PWM pulses occur every 5.005 ms
+ */
+ kPeriodMultiplier_1X = 1,
+ /**
+ * Skip every other pulse. PWM pulses occur every 10.010 ms
+ */
+ kPeriodMultiplier_2X = 2,
+ /**
+ * Skip three out of four pulses. PWM pulses occur every 20.020 ms
+ */
+ kPeriodMultiplier_4X = 4
+ };
+
+ /**
+ * Allocate a PWM given a channel number.
+ *
+ * Checks channel value range and allocates the appropriate channel.
+ * The allocation is only done to help users ensure that they don't double
+ * assign channels.
+ *
+ * @param channel The PWM channel number. 0-9 are on-board, 10-19 are on the
+ * MXP port
+ */
+ explicit PWM(int channel);
+
+ /**
+ * Free the PWM channel.
+ *
+ * Free the resource associated with the PWM channel and set the value to 0.
+ */
+ ~PWM() override;
+
+ PWM(PWM&& rhs);
+ PWM& operator=(PWM&& rhs);
+
+ // MotorSafety interface
+ void StopMotor() override;
+ void GetDescription(wpi::raw_ostream& desc) const override;
+
+ /**
+ * Set the PWM value directly to the hardware.
+ *
+ * Write a raw value to a PWM channel.
+ *
+ * @param value Raw PWM value.
+ */
+ virtual void SetRaw(uint16_t value);
+
+ /**
+ * Get the PWM value directly from the hardware.
+ *
+ * Read a raw value from a PWM channel.
+ *
+ * @return Raw PWM control value.
+ */
+ virtual uint16_t GetRaw() const;
+
+ /**
+ * Set the PWM value based on a position.
+ *
+ * This is intended to be used by servos.
+ *
+ * @pre SetMaxPositivePwm() called.
+ * @pre SetMinNegativePwm() called.
+ *
+ * @param pos The position to set the servo between 0.0 and 1.0.
+ */
+ virtual void SetPosition(double pos);
+
+ /**
+ * Get the PWM value in terms of a position.
+ *
+ * This is intended to be used by servos.
+ *
+ * @pre SetMaxPositivePwm() called.
+ * @pre SetMinNegativePwm() called.
+ *
+ * @return The position the servo is set to between 0.0 and 1.0.
+ */
+ virtual double GetPosition() const;
+
+ /**
+ * Set the PWM value based on a speed.
+ *
+ * This is intended to be used by speed controllers.
+ *
+ * @pre SetMaxPositivePwm() called.
+ * @pre SetMinPositivePwm() called.
+ * @pre SetCenterPwm() called.
+ * @pre SetMaxNegativePwm() called.
+ * @pre SetMinNegativePwm() called.
+ *
+ * @param speed The speed to set the speed controller between -1.0 and 1.0.
+ */
+ virtual void SetSpeed(double speed);
+
+ /**
+ * Get the PWM value in terms of speed.
+ *
+ * This is intended to be used by speed controllers.
+ *
+ * @pre SetMaxPositivePwm() called.
+ * @pre SetMinPositivePwm() called.
+ * @pre SetMaxNegativePwm() called.
+ * @pre SetMinNegativePwm() called.
+ *
+ * @return The most recently set speed between -1.0 and 1.0.
+ */
+ virtual double GetSpeed() const;
+
+ /**
+ * Temporarily disables the PWM output. The next set call will reenable
+ * the output.
+ */
+ virtual void SetDisabled();
+
+ /**
+ * Slow down the PWM signal for old devices.
+ *
+ * @param mult The period multiplier to apply to this channel
+ */
+ void SetPeriodMultiplier(PeriodMultiplier mult);
+
+ void SetZeroLatch();
+
+ /**
+ * Optionally eliminate the deadband from a speed controller.
+ *
+ * @param eliminateDeadband If true, set the motor curve on the Jaguar to
+ * eliminate the deadband in the middle of the range.
+ * Otherwise, keep the full range without modifying
+ * any values.
+ */
+ void EnableDeadbandElimination(bool eliminateDeadband);
+
+ /**
+ * Set the bounds on the PWM pulse widths.
+ *
+ * This sets the bounds on the PWM values for a particular type of controller.
+ * The values determine the upper and lower speeds as well as the deadband
+ * bracket.
+ *
+ * @param max The max PWM pulse width in ms
+ * @param deadbandMax The high end of the deadband range pulse width in ms
+ * @param center The center (off) pulse width in ms
+ * @param deadbandMin The low end of the deadband pulse width in ms
+ * @param min The minimum pulse width in ms
+ */
+ void SetBounds(double max, double deadbandMax, double center,
+ double deadbandMin, double min);
+
+ /**
+ * Set the bounds on the PWM values.
+ *
+ * This sets the bounds on the PWM values for a particular each type of
+ * controller. The values determine the upper and lower speeds as well as the
+ * deadband bracket.
+ *
+ * @param max The Minimum pwm value
+ * @param deadbandMax The high end of the deadband range
+ * @param center The center speed (off)
+ * @param deadbandMin The low end of the deadband range
+ * @param min The minimum pwm value
+ */
+ void SetRawBounds(int max, int deadbandMax, int center, int deadbandMin,
+ int min);
+
+ /**
+ * Get the bounds on the PWM values.
+ *
+ * This Gets the bounds on the PWM values for a particular each type of
+ * controller. The values determine the upper and lower speeds as well as the
+ * deadband bracket.
+ *
+ * @param max The Minimum pwm value
+ * @param deadbandMax The high end of the deadband range
+ * @param center The center speed (off)
+ * @param deadbandMin The low end of the deadband range
+ * @param min The minimum pwm value
+ */
+ void GetRawBounds(int32_t* max, int32_t* deadbandMax, int32_t* center,
+ int32_t* deadbandMin, int32_t* min);
+
+ int GetChannel() const;
+
+ protected:
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ int m_channel;
+ HAL_DigitalHandle m_handle = HAL_kInvalidHandle;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/PWMSpeedController.h b/wpilibc/src/main/native/include/frc/PWMSpeedController.h
new file mode 100644
index 0000000..5222559
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/PWMSpeedController.h
@@ -0,0 +1,70 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PWM.h"
+#include "frc/SpeedController.h"
+
+namespace frc {
+
+/**
+ * Common base class for all PWM Speed Controllers.
+ */
+class PWMSpeedController : public PWM, public SpeedController {
+ public:
+ PWMSpeedController(PWMSpeedController&&) = default;
+ PWMSpeedController& operator=(PWMSpeedController&&) = default;
+
+ /**
+ * Set the PWM value.
+ *
+ * The PWM value is set using a range of -1.0 to 1.0, appropriately scaling
+ * the value for the FPGA.
+ *
+ * @param speed The speed value between -1.0 and 1.0 to set.
+ */
+ void Set(double value) override;
+
+ /**
+ * Get the recently set value of the PWM.
+ *
+ * @return The most recently set value for the PWM between -1.0 and 1.0.
+ */
+ double Get() const override;
+
+ void SetInverted(bool isInverted) override;
+
+ bool GetInverted() const override;
+
+ void Disable() override;
+
+ void StopMotor() override;
+
+ /**
+ * Write out the PID value as seen in the PIDOutput base object.
+ *
+ * @param output Write out the PWM value as was found in the PIDController
+ */
+ void PIDWrite(double output) override;
+
+ protected:
+ /**
+ * Constructor for a PWM Speed Controller connected via PWM.
+ *
+ * @param channel The PWM channel that the controller is attached to. 0-9 are
+ * on-board, 10-19 are on the MXP port
+ */
+ explicit PWMSpeedController(int channel);
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ bool m_isInverted = false;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/PWMTalonSRX.h b/wpilibc/src/main/native/include/frc/PWMTalonSRX.h
new file mode 100644
index 0000000..9260e1e
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/PWMTalonSRX.h
@@ -0,0 +1,32 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PWMSpeedController.h"
+
+namespace frc {
+
+/**
+ * Cross the Road Electronics (CTRE) Talon SRX Speed Controller with PWM
+ * control.
+ */
+class PWMTalonSRX : public PWMSpeedController {
+ public:
+ /**
+ * Construct a PWMTalonSRX connected via PWM.
+ *
+ * @param channel The PWM channel that the PWMTalonSRX is attached to. 0-9 are
+ * on-board, 10-19 are on the MXP port
+ */
+ explicit PWMTalonSRX(int channel);
+
+ PWMTalonSRX(PWMTalonSRX&&) = default;
+ PWMTalonSRX& operator=(PWMTalonSRX&&) = default;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/PWMVictorSPX.h b/wpilibc/src/main/native/include/frc/PWMVictorSPX.h
new file mode 100644
index 0000000..d7112c9
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/PWMVictorSPX.h
@@ -0,0 +1,32 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PWMSpeedController.h"
+
+namespace frc {
+
+/**
+ * Cross the Road Electronics (CTRE) Victor SPX Speed Controller with PWM
+ * control.
+ */
+class PWMVictorSPX : public PWMSpeedController {
+ public:
+ /**
+ * Construct a PWMVictorSPX connected via PWM.
+ *
+ * @param channel The PWM channel that the PWMVictorSPX is attached to. 0-9
+ * are on-board, 10-19 are on the MXP port
+ */
+ explicit PWMVictorSPX(int channel);
+
+ PWMVictorSPX(PWMVictorSPX&&) = default;
+ PWMVictorSPX& operator=(PWMVictorSPX&&) = default;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/PowerDistributionPanel.h b/wpilibc/src/main/native/include/frc/PowerDistributionPanel.h
new file mode 100644
index 0000000..2d7f65c
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/PowerDistributionPanel.h
@@ -0,0 +1,89 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <hal/Types.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * Class for getting voltage, current, temperature, power and energy from the
+ * CAN PDP.
+ */
+class PowerDistributionPanel : public ErrorBase, public SendableBase {
+ public:
+ PowerDistributionPanel();
+ explicit PowerDistributionPanel(int module);
+
+ PowerDistributionPanel(PowerDistributionPanel&&) = default;
+ PowerDistributionPanel& operator=(PowerDistributionPanel&&) = default;
+
+ /**
+ * Query the input voltage of the PDP.
+ *
+ * @return The voltage of the PDP in volts
+ */
+ double GetVoltage() const;
+
+ /**
+ * Query the temperature of the PDP.
+ *
+ * @return The temperature of the PDP in degrees Celsius
+ */
+ double GetTemperature() const;
+
+ /**
+ * Query the current of a single channel of the PDP.
+ *
+ * @return The current of one of the PDP channels (channels 0-15) in Amperes
+ */
+ double GetCurrent(int channel) const;
+
+ /**
+ * Query the total current of all monitored PDP channels (0-15).
+ *
+ * @return The the total current drawn from the PDP channels in Amperes
+ */
+ double GetTotalCurrent() const;
+
+ /**
+ * Query the total power drawn from the monitored PDP channels.
+ *
+ * @return The the total power drawn from the PDP channels in Watts
+ */
+ double GetTotalPower() const;
+
+ /**
+ * Query the total energy drawn from the monitored PDP channels.
+ *
+ * @return The the total energy drawn from the PDP channels in Joules
+ */
+ double GetTotalEnergy() const;
+
+ /**
+ * Reset the total energy drawn from the PDP.
+ *
+ * @see PowerDistributionPanel#GetTotalEnergy
+ */
+ void ResetTotalEnergy();
+
+ /**
+ * Remove all of the fault flags on the PDP.
+ */
+ void ClearStickyFaults();
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ HAL_PDPHandle m_handle = HAL_kInvalidHandle;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Preferences.h b/wpilibc/src/main/native/include/frc/Preferences.h
new file mode 100644
index 0000000..57678a8
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Preferences.h
@@ -0,0 +1,206 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <networktables/NetworkTable.h>
+
+#include "frc/ErrorBase.h"
+
+namespace frc {
+
+/**
+ * The preferences class provides a relatively simple way to save important
+ * values to the roboRIO to access the next time the roboRIO is booted.
+ *
+ * This class loads and saves from a file inside the roboRIO. The user cannot
+ * access the file directly, but may modify values at specific fields which will
+ * then be automatically periodically saved to the file by the NetworkTable
+ * server.
+ *
+ * This class is thread safe.
+ *
+ * This will also interact with {@link NetworkTable} by creating a table called
+ * "Preferences" with all the key-value pairs.
+ */
+class Preferences : public ErrorBase {
+ public:
+ /**
+ * Get the one and only {@link Preferences} object.
+ *
+ * @return pointer to the {@link Preferences}
+ */
+ static Preferences* GetInstance();
+
+ /**
+ * Returns a vector of all the keys.
+ *
+ * @return a vector of the keys
+ */
+ std::vector<std::string> GetKeys();
+
+ /**
+ * Returns the string at the given key. If this table does not have a value
+ * for that position, then the given defaultValue will be returned.
+ *
+ * @param key the key
+ * @param defaultValue the value to return if none exists in the table
+ * @return either the value in the table, or the defaultValue
+ */
+ std::string GetString(wpi::StringRef key, wpi::StringRef defaultValue = "");
+
+ /**
+ * Returns the int at the given key. If this table does not have a value for
+ * that position, then the given defaultValue value will be returned.
+ *
+ * @param key the key
+ * @param defaultValue the value to return if none exists in the table
+ * @return either the value in the table, or the defaultValue
+ */
+ int GetInt(wpi::StringRef key, int defaultValue = 0);
+
+ /**
+ * Returns the double at the given key. If this table does not have a value
+ * for that position, then the given defaultValue value will be returned.
+ *
+ * @param key the key
+ * @param defaultValue the value to return if none exists in the table
+ * @return either the value in the table, or the defaultValue
+ */
+ double GetDouble(wpi::StringRef key, double defaultValue = 0.0);
+
+ /**
+ * Returns the float at the given key. If this table does not have a value
+ * for that position, then the given defaultValue value will be returned.
+ *
+ * @param key the key
+ * @param defaultValue the value to return if none exists in the table
+ * @return either the value in the table, or the defaultValue
+ */
+ float GetFloat(wpi::StringRef key, float defaultValue = 0.0);
+
+ /**
+ * Returns the boolean at the given key. If this table does not have a value
+ * for that position, then the given defaultValue value will be returned.
+ *
+ * @param key the key
+ * @param defaultValue the value to return if none exists in the table
+ * @return either the value in the table, or the defaultValue
+ */
+ bool GetBoolean(wpi::StringRef key, bool defaultValue = false);
+
+ /**
+ * Returns the long (int64_t) at the given key. If this table does not have a
+ * value for that position, then the given defaultValue value will be
+ * returned.
+ *
+ * @param key the key
+ * @param defaultValue the value to return if none exists in the table
+ * @return either the value in the table, or the defaultValue
+ */
+ int64_t GetLong(wpi::StringRef key, int64_t defaultValue = 0);
+
+ /**
+ * Puts the given string into the preferences table.
+ *
+ * The value may not have quotation marks, nor may the key have any whitespace
+ * nor an equals sign.
+ *
+ * @param key the key
+ * @param value the value
+ */
+ void PutString(wpi::StringRef key, wpi::StringRef value);
+
+ /**
+ * Puts the given int into the preferences table.
+ *
+ * The key may not have any whitespace nor an equals sign.
+ *
+ * @param key the key
+ * @param value the value
+ */
+ void PutInt(wpi::StringRef key, int value);
+
+ /**
+ * Puts the given double into the preferences table.
+ *
+ * The key may not have any whitespace nor an equals sign.
+ *
+ * @param key the key
+ * @param value the value
+ */
+ void PutDouble(wpi::StringRef key, double value);
+
+ /**
+ * Puts the given float into the preferences table.
+ *
+ * The key may not have any whitespace nor an equals sign.
+ *
+ * @param key the key
+ * @param value the value
+ */
+ void PutFloat(wpi::StringRef key, float value);
+
+ /**
+ * Puts the given boolean into the preferences table.
+ *
+ * The key may not have any whitespace nor an equals sign.
+ *
+ * @param key the key
+ * @param value the value
+ */
+ void PutBoolean(wpi::StringRef key, bool value);
+
+ /**
+ * Puts the given long (int64_t) into the preferences table.
+ *
+ * The key may not have any whitespace nor an equals sign.
+ *
+ * @param key the key
+ * @param value the value
+ */
+ void PutLong(wpi::StringRef key, int64_t value);
+
+ /**
+ * Returns whether or not there is a key with the given name.
+ *
+ * @param key the key
+ * @return if there is a value at the given key
+ */
+ bool ContainsKey(wpi::StringRef key);
+
+ /**
+ * Remove a preference.
+ *
+ * @param key the key
+ */
+ void Remove(wpi::StringRef key);
+
+ /**
+ * Remove all preferences.
+ */
+ void RemoveAll();
+
+ protected:
+ Preferences();
+ virtual ~Preferences() = default;
+
+ Preferences(Preferences&&) = default;
+ Preferences& operator=(Preferences&&) = default;
+
+ private:
+ std::shared_ptr<nt::NetworkTable> m_table;
+ NT_EntryListener m_listener;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Relay.h b/wpilibc/src/main/native/include/frc/Relay.h
new file mode 100644
index 0000000..6fb21b5
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Relay.h
@@ -0,0 +1,105 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <hal/Types.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/MotorSafety.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * Class for Spike style relay outputs.
+ *
+ * Relays are intended to be connected to spikes or similar relays. The relay
+ * channels controls a pair of pins that are either both off, one on, the other
+ * on, or both on. This translates into two spike outputs at 0v, one at 12v and
+ * one at 0v, one at 0v and the other at 12v, or two spike outputs at 12V. This
+ * allows off, full forward, or full reverse control of motors without variable
+ * speed. It also allows the two channels (forward and reverse) to be used
+ * independently for something that does not care about voltage polarity (like
+ * a solenoid).
+ */
+class Relay : public MotorSafety, public SendableBase {
+ public:
+ enum Value { kOff, kOn, kForward, kReverse };
+ enum Direction { kBothDirections, kForwardOnly, kReverseOnly };
+
+ /**
+ * Relay constructor given a channel.
+ *
+ * This code initializes the relay and reserves all resources that need to be
+ * locked. Initially the relay is set to both lines at 0v.
+ *
+ * @param channel The channel number (0-3).
+ * @param direction The direction that the Relay object will control.
+ */
+ explicit Relay(int channel, Direction direction = kBothDirections);
+
+ /**
+ * Free the resource associated with a relay.
+ *
+ * The relay channels are set to free and the relay output is turned off.
+ */
+ ~Relay() override;
+
+ Relay(Relay&& rhs);
+ Relay& operator=(Relay&& rhs);
+
+ /**
+ * Set the relay state.
+ *
+ * Valid values depend on which directions of the relay are controlled by the
+ * object.
+ *
+ * When set to kBothDirections, the relay can be any of the four states:
+ * 0v-0v, 0v-12v, 12v-0v, 12v-12v
+ *
+ * When set to kForwardOnly or kReverseOnly, you can specify the constant for
+ * the direction or you can simply specify kOff and kOn. Using only kOff and
+ * kOn is recommended.
+ *
+ * @param value The state to set the relay.
+ */
+ void Set(Value value);
+
+ /**
+ * Get the Relay State
+ *
+ * Gets the current state of the relay.
+ *
+ * When set to kForwardOnly or kReverseOnly, value is returned as kOn/kOff not
+ * kForward/kReverse (per the recommendation in Set).
+ *
+ * @return The current state of the relay as a Relay::Value
+ */
+ Value Get() const;
+
+ int GetChannel() const;
+
+ // MotorSafety interface
+ void StopMotor() override;
+
+ void GetDescription(wpi::raw_ostream& desc) const override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ int m_channel;
+ Direction m_direction;
+
+ HAL_RelayHandle m_forwardHandle = HAL_kInvalidHandle;
+ HAL_RelayHandle m_reverseHandle = HAL_kInvalidHandle;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Resource.h b/wpilibc/src/main/native/include/frc/Resource.h
new file mode 100644
index 0000000..9df2196
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Resource.h
@@ -0,0 +1,95 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <wpi/mutex.h>
+
+#include "frc/ErrorBase.h"
+
+namespace frc {
+
+/**
+ * The Resource class is a convenient way to track allocated resources.
+ *
+ * It tracks them as indicies in the range [0 .. elements - 1]. E.g. the library
+ * uses this to track hardware channel allocation.
+ *
+ * The Resource class does not allocate the hardware channels or other
+ * resources; it just tracks which indices were marked in use by Allocate and
+ * not yet freed by Free.
+ */
+class Resource : public ErrorBase {
+ public:
+ virtual ~Resource() = default;
+
+ Resource(Resource&&) = default;
+ Resource& operator=(Resource&&) = default;
+
+ /**
+ * Factory method to create a Resource allocation-tracker *if* needed.
+ *
+ * @param r address of the caller's Resource pointer. If *r == nullptr,
+ * this will construct a Resource and make *r point to it. If
+ * *r != nullptr, i.e. the caller already has a Resource
+ * instance, this won't do anything.
+ * @param elements the number of elements for this Resource allocator to
+ * track, that is, it will allocate resource numbers in the
+ * range [0 .. elements - 1].
+ */
+ static void CreateResourceObject(std::unique_ptr<Resource>& r,
+ uint32_t elements);
+
+ /**
+ * Allocate storage for a new instance of Resource.
+ *
+ * Allocate a bool array of values that will get initialized to indicate that
+ * no resources have been allocated yet. The indicies of the resources are
+ * [0 .. elements - 1].
+ */
+ explicit Resource(uint32_t size);
+
+ /**
+ * Allocate a resource.
+ *
+ * When a resource is requested, mark it allocated. In this case, a free
+ * resource value within the range is located and returned after it is marked
+ * allocated.
+ */
+ uint32_t Allocate(const std::string& resourceDesc);
+
+ /**
+ * Allocate a specific resource value.
+ *
+ * The user requests a specific resource value, i.e. channel number and it is
+ * verified unallocated, then returned.
+ */
+ uint32_t Allocate(uint32_t index, const std::string& resourceDesc);
+
+ /**
+ * Free an allocated resource.
+ *
+ * After a resource is no longer needed, for example a destructor is called
+ * for a channel assignment class, Free will release the resource value so it
+ * can be reused somewhere else in the program.
+ */
+ void Free(uint32_t index);
+
+ private:
+ std::vector<bool> m_isAllocated;
+ wpi::mutex m_allocateMutex;
+
+ static wpi::mutex m_createMutex;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/RobotBase.h b/wpilibc/src/main/native/include/frc/RobotBase.h
new file mode 100644
index 0000000..eee07d6
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/RobotBase.h
@@ -0,0 +1,142 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <thread>
+
+#include <wpi/raw_ostream.h>
+
+#include "frc/Base.h"
+
+namespace frc {
+
+class DriverStation;
+
+int RunHALInitialization();
+
+template <class Robot>
+int StartRobot() {
+ int halInit = RunHALInitialization();
+ if (halInit != 0) {
+ return halInit;
+ }
+ static Robot robot;
+ robot.StartCompetition();
+
+ return 0;
+}
+
+#define START_ROBOT_CLASS(_ClassName_) \
+ WPI_DEPRECATED("Call frc::StartRobot<" #_ClassName_ \
+ ">() in your own main() instead of using the " \
+ "START_ROBOT_CLASS(" #_ClassName_ ") macro.") \
+ int StartRobotClassImpl() { return frc::StartRobot<_ClassName_>(); } \
+ int main() { return StartRobotClassImpl(); }
+
+/**
+ * Implement a Robot Program framework.
+ *
+ * The RobotBase class is intended to be subclassed by a user creating a robot
+ * program. Overridden Autonomous() and OperatorControl() methods are called at
+ * the appropriate time as the match proceeds. In the current implementation,
+ * the Autonomous code will run to completion before the OperatorControl code
+ * could start. In the future the Autonomous code might be spawned as a task,
+ * then killed at the end of the Autonomous period.
+ */
+class RobotBase {
+ public:
+ /**
+ * Determine if the Robot is currently enabled.
+ *
+ * @return True if the Robot is currently enabled by the field controls.
+ */
+ bool IsEnabled() const;
+
+ /**
+ * Determine if the Robot is currently disabled.
+ *
+ * @return True if the Robot is currently disabled by the field controls.
+ */
+ bool IsDisabled() const;
+
+ /**
+ * Determine if the robot is currently in Autonomous mode.
+ *
+ * @return True if the robot is currently operating Autonomously as determined
+ * by the field controls.
+ */
+ bool IsAutonomous() const;
+
+ /**
+ * Determine if the robot is currently in Operator Control mode.
+ *
+ * @return True if the robot is currently operating in Tele-Op mode as
+ * determined by the field controls.
+ */
+ bool IsOperatorControl() const;
+
+ /**
+ * Determine if the robot is currently in Test mode.
+ *
+ * @return True if the robot is currently running tests as determined by the
+ * field controls.
+ */
+ bool IsTest() const;
+
+ /**
+ * Indicates if new data is available from the driver station.
+ *
+ * @return Has new data arrived over the network since the last time this
+ * function was called?
+ */
+ bool IsNewDataAvailable() const;
+
+ /**
+ * Gets the ID of the main robot thread.
+ */
+ static std::thread::id GetThreadId();
+
+ virtual void StartCompetition() = 0;
+
+ static constexpr bool IsReal() {
+#ifdef __FRC_ROBORIO__
+ return true;
+#else
+ return false;
+#endif
+ }
+
+ static constexpr bool IsSimulation() { return !IsReal(); }
+
+ protected:
+ /**
+ * Constructor for a generic robot program.
+ *
+ * User code should be placed in the constructor that runs before the
+ * Autonomous or Operator Control period starts. The constructor will run to
+ * completion before Autonomous is entered.
+ *
+ * This must be used to ensure that the communications code starts. In the
+ * future it would be nice to put this code into it's own task that loads on
+ * boot so ensure that it runs.
+ */
+ RobotBase();
+
+ virtual ~RobotBase();
+
+ // m_ds isn't moved in these because DriverStation is a singleton; every
+ // instance of RobotBase has a reference to the same object.
+ RobotBase(RobotBase&&);
+ RobotBase& operator=(RobotBase&&);
+
+ DriverStation& m_ds;
+
+ static std::thread::id m_threadId;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/RobotController.h b/wpilibc/src/main/native/include/frc/RobotController.h
new file mode 100644
index 0000000..fae136b
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/RobotController.h
@@ -0,0 +1,188 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+namespace frc {
+
+struct CANStatus {
+ float percentBusUtilization;
+ int busOffCount;
+ int txFullCount;
+ int receiveErrorCount;
+ int transmitErrorCount;
+};
+
+class RobotController {
+ public:
+ RobotController() = delete;
+
+ /**
+ * Return the FPGA Version number.
+ *
+ * For now, expect this to be competition year.
+ *
+ * @return FPGA Version number.
+ */
+ static int GetFPGAVersion();
+
+ /**
+ * Return the FPGA Revision number.
+ *
+ * The format of the revision is 3 numbers. The 12 most significant bits are
+ * the Major Revision. The next 8 bits are the Minor Revision. The 12 least
+ * significant bits are the Build Number.
+ *
+ * @return FPGA Revision number.
+ */
+ static int64_t GetFPGARevision();
+
+ /**
+ * Read the microsecond-resolution timer on the FPGA.
+ *
+ * @return The current time in microseconds according to the FPGA (since FPGA
+ * reset).
+ */
+ static uint64_t GetFPGATime();
+
+ /**
+ * Get the state of the "USER" button on the roboRIO.
+ *
+ * @return True if the button is currently pressed down
+ */
+ static bool GetUserButton();
+
+ /**
+ * Check if the FPGA outputs are enabled.
+ *
+ * The outputs may be disabled if the robot is disabled or e-stopped, the
+ * watchdog has expired, or if the roboRIO browns out.
+ *
+ * @return True if the FPGA outputs are enabled.
+ */
+ static bool IsSysActive();
+
+ /**
+ * Check if the system is browned out.
+ *
+ * @return True if the system is browned out
+ */
+ static bool IsBrownedOut();
+
+ /**
+ * Get the input voltage to the robot controller.
+ *
+ * @return The controller input voltage value in Volts
+ */
+ static double GetInputVoltage();
+
+ /**
+ * Get the input current to the robot controller.
+ *
+ * @return The controller input current value in Amps
+ */
+ static double GetInputCurrent();
+
+ /**
+ * Get the voltage of the 3.3V rail.
+ *
+ * @return The controller 3.3V rail voltage value in Volts
+ */
+ static double GetVoltage3V3();
+
+ /**
+ * Get the current output of the 3.3V rail.
+ *
+ * @return The controller 3.3V rail output current value in Amps
+ */
+ static double GetCurrent3V3();
+
+ /**
+ * Get the enabled state of the 3.3V rail. The rail may be disabled due to a
+ * controller brownout, a short circuit on the rail, or controller
+ * over-voltage.
+ *
+ * @return The controller 3.3V rail enabled value. True for enabled.
+ */
+ static bool GetEnabled3V3();
+
+ /**
+ * Get the count of the total current faults on the 3.3V rail since the
+ * controller has booted.
+ *
+ * @return The number of faults
+ */
+ static int GetFaultCount3V3();
+
+ /**
+ * Get the voltage of the 5V rail.
+ *
+ * @return The controller 5V rail voltage value in Volts
+ */
+ static double GetVoltage5V();
+
+ /**
+ * Get the current output of the 5V rail.
+ *
+ * @return The controller 5V rail output current value in Amps
+ */
+ static double GetCurrent5V();
+
+ /**
+ * Get the enabled state of the 5V rail. The rail may be disabled due to a
+ * controller brownout, a short circuit on the rail, or controller
+ * over-voltage.
+ *
+ * @return The controller 5V rail enabled value. True for enabled.
+ */
+ static bool GetEnabled5V();
+
+ /**
+ * Get the count of the total current faults on the 5V rail since the
+ * controller has booted.
+ *
+ * @return The number of faults
+ */
+ static int GetFaultCount5V();
+
+ /**
+ * Get the voltage of the 6V rail.
+ *
+ * @return The controller 6V rail voltage value in Volts
+ */
+ static double GetVoltage6V();
+
+ /**
+ * Get the current output of the 6V rail.
+ *
+ * @return The controller 6V rail output current value in Amps
+ */
+ static double GetCurrent6V();
+
+ /**
+ * Get the enabled state of the 6V rail. The rail may be disabled due to a
+ * controller brownout, a short circuit on the rail, or controller
+ * over-voltage.
+ *
+ * @return The controller 6V rail enabled value. True for enabled.
+ */
+ static bool GetEnabled6V();
+
+ /**
+ * Get the count of the total current faults on the 6V rail since the
+ * controller has booted.
+ *
+ * @return The number of faults.
+ */
+ static int GetFaultCount6V();
+
+ static CANStatus GetCANStatus();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/RobotDrive.h b/wpilibc/src/main/native/include/frc/RobotDrive.h
new file mode 100644
index 0000000..3580003
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/RobotDrive.h
@@ -0,0 +1,453 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <wpi/deprecated.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/MotorSafety.h"
+
+namespace frc {
+
+class SpeedController;
+class GenericHID;
+
+/**
+ * Utility class for handling Robot drive based on a definition of the motor
+ * configuration.
+ *
+ * The robot drive class handles basic driving for a robot. Currently, 2 and 4
+ * motor tank and mecanum drive trains are supported. In the future other drive
+ * types like swerve might be implemented. Motor channel numbers are passed
+ * supplied on creation of the class. Those are used for either the Drive
+ * function (intended for hand created drive code, such as autonomous) or with
+ * the Tank/Arcade functions intended to be used for Operator Control driving.
+ */
+class RobotDrive : public MotorSafety {
+ public:
+ enum MotorType {
+ kFrontLeftMotor = 0,
+ kFrontRightMotor = 1,
+ kRearLeftMotor = 2,
+ kRearRightMotor = 3
+ };
+
+ /**
+ * Constructor for RobotDrive with 2 motors specified with channel numbers.
+ *
+ * Set up parameters for a two wheel drive system where the
+ * left and right motor pwm channels are specified in the call.
+ * This call assumes Talons for controlling the motors.
+ *
+ * @param leftMotorChannel The PWM channel number that drives the left motor.
+ * 0-9 are on-board, 10-19 are on the MXP port
+ * @param rightMotorChannel The PWM channel number that drives the right
+ * motor. 0-9 are on-board, 10-19 are on the MXP port
+ */
+ WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
+ RobotDrive(int leftMotorChannel, int rightMotorChannel);
+
+ /**
+ * Constructor for RobotDrive with 4 motors specified with channel numbers.
+ *
+ * Set up parameters for a four wheel drive system where all four motor
+ * pwm channels are specified in the call.
+ * This call assumes Talons for controlling the motors.
+ *
+ * @param frontLeftMotor Front left motor channel number. 0-9 are on-board,
+ * 10-19 are on the MXP port
+ * @param rearLeftMotor Rear Left motor channel number. 0-9 are on-board,
+ * 10-19 are on the MXP port
+ * @param frontRightMotor Front right motor channel number. 0-9 are on-board,
+ * 10-19 are on the MXP port
+ * @param rearRightMotor Rear Right motor channel number. 0-9 are on-board,
+ * 10-19 are on the MXP port
+ */
+ WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
+ RobotDrive(int frontLeftMotorChannel, int rearLeftMotorChannel,
+ int frontRightMotorChannel, int rearRightMotorChannel);
+
+ /**
+ * Constructor for RobotDrive with 2 motors specified as SpeedController
+ * objects.
+ *
+ * The SpeedController version of the constructor enables programs to use the
+ * RobotDrive classes with subclasses of the SpeedController objects, for
+ * example, versions with ramping or reshaping of the curve to suit motor bias
+ * or deadband elimination.
+ *
+ * @param leftMotor The left SpeedController object used to drive the robot.
+ * @param rightMotor The right SpeedController object used to drive the robot.
+ */
+ WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
+ RobotDrive(SpeedController* leftMotor, SpeedController* rightMotor);
+
+ WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
+ RobotDrive(SpeedController& leftMotor, SpeedController& rightMotor);
+
+ WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
+ RobotDrive(std::shared_ptr<SpeedController> leftMotor,
+ std::shared_ptr<SpeedController> rightMotor);
+
+ /**
+ * Constructor for RobotDrive with 4 motors specified as SpeedController
+ * objects.
+ *
+ * Speed controller input version of RobotDrive (see previous comments).
+ *
+ * @param frontLeftMotor The front left SpeedController object used to drive
+ * the robot.
+ * @param rearLeftMotor The back left SpeedController object used to drive
+ * the robot.
+ * @param frontRightMotor The front right SpeedController object used to drive
+ * the robot.
+ * @param rearRightMotor The back right SpeedController object used to drive
+ * the robot.
+ */
+ WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
+ RobotDrive(SpeedController* frontLeftMotor, SpeedController* rearLeftMotor,
+ SpeedController* frontRightMotor, SpeedController* rearRightMotor);
+
+ WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
+ RobotDrive(SpeedController& frontLeftMotor, SpeedController& rearLeftMotor,
+ SpeedController& frontRightMotor, SpeedController& rearRightMotor);
+
+ WPI_DEPRECATED("Use DifferentialDrive or MecanumDrive classes instead.")
+ RobotDrive(std::shared_ptr<SpeedController> frontLeftMotor,
+ std::shared_ptr<SpeedController> rearLeftMotor,
+ std::shared_ptr<SpeedController> frontRightMotor,
+ std::shared_ptr<SpeedController> rearRightMotor);
+
+ virtual ~RobotDrive() = default;
+
+ RobotDrive(RobotDrive&&) = default;
+ RobotDrive& operator=(RobotDrive&&) = default;
+
+ /**
+ * Drive the motors at "outputMagnitude" and "curve".
+ *
+ * Both outputMagnitude and curve are -1.0 to +1.0 values, where 0.0
+ * represents stopped and not turning. curve < 0 will turn left and curve > 0
+ * will turn right.
+ *
+ * The algorithm for steering provides a constant turn radius for any normal
+ * speed range, both forward and backward. Increasing m_sensitivity causes
+ * sharper turns for fixed values of curve.
+ *
+ * This function will most likely be used in an autonomous routine.
+ *
+ * @param outputMagnitude The speed setting for the outside wheel in a turn,
+ * forward or backwards, +1 to -1.
+ * @param curve The rate of turn, constant for different forward
+ * speeds. Set curve < 0 for left turn or curve > 0 for
+ * right turn.
+ *
+ * Set curve = e^(-r/w) to get a turn radius r for wheelbase w of your robot.
+ * Conversely, turn radius r = -ln(curve)*w for a given value of curve and
+ * wheelbase w.
+ */
+ void Drive(double outputMagnitude, double curve);
+
+ /**
+ * Provide tank steering using the stored robot configuration.
+ *
+ * Drive the robot using two joystick inputs. The Y-axis will be selected from
+ * each Joystick object.
+ *
+ * @param leftStick The joystick to control the left side of the robot.
+ * @param rightStick The joystick to control the right side of the robot.
+ * @param squaredInputs If true, the sensitivity will be decreased for small
+ * values
+ */
+ void TankDrive(GenericHID* leftStick, GenericHID* rightStick,
+ bool squaredInputs = true);
+
+ /**
+ * Provide tank steering using the stored robot configuration.
+ *
+ * Drive the robot using two joystick inputs. The Y-axis will be selected from
+ * each Joystick object.
+ *
+ * @param leftStick The joystick to control the left side of the robot.
+ * @param rightStick The joystick to control the right side of the robot.
+ * @param squaredInputs If true, the sensitivity will be decreased for small
+ * values
+ */
+ void TankDrive(GenericHID& leftStick, GenericHID& rightStick,
+ bool squaredInputs = true);
+
+ /**
+ * Provide tank steering using the stored robot configuration.
+ *
+ * This function lets you pick the axis to be used on each Joystick object for
+ * the left and right sides of the robot.
+ *
+ * @param leftStick The Joystick object to use for the left side of the
+ * robot.
+ * @param leftAxis The axis to select on the left side Joystick object.
+ * @param rightStick The Joystick object to use for the right side of the
+ * robot.
+ * @param rightAxis The axis to select on the right side Joystick object.
+ * @param squaredInputs If true, the sensitivity will be decreased for small
+ * values
+ */
+ void TankDrive(GenericHID* leftStick, int leftAxis, GenericHID* rightStick,
+ int rightAxis, bool squaredInputs = true);
+
+ void TankDrive(GenericHID& leftStick, int leftAxis, GenericHID& rightStick,
+ int rightAxis, bool squaredInputs = true);
+
+ /**
+ * Provide tank steering using the stored robot configuration.
+ *
+ * This function lets you directly provide joystick values from any source.
+ *
+ * @param leftValue The value of the left stick.
+ * @param rightValue The value of the right stick.
+ * @param squaredInputs If true, the sensitivity will be decreased for small
+ * values
+ */
+ void TankDrive(double leftValue, double rightValue,
+ bool squaredInputs = true);
+
+ /**
+ * Arcade drive implements single stick driving.
+ *
+ * Given a single Joystick, the class assumes the Y axis for the move value
+ * and the X axis for the rotate value. (Should add more information here
+ * regarding the way that arcade drive works.)
+ *
+ * @param stick The joystick to use for Arcade single-stick driving.
+ * The Y-axis will be selected for forwards/backwards and
+ * the X-axis will be selected for rotation rate.
+ * @param squaredInputs If true, the sensitivity will be decreased for small
+ * values
+ */
+ void ArcadeDrive(GenericHID* stick, bool squaredInputs = true);
+
+ /**
+ * Arcade drive implements single stick driving.
+ *
+ * Given a single Joystick, the class assumes the Y axis for the move value
+ * and the X axis for the rotate value. (Should add more information here
+ * regarding the way that arcade drive works.)
+ *
+ * @param stick The joystick to use for Arcade single-stick driving.
+ * The Y-axis will be selected for forwards/backwards and
+ * the X-axis will be selected for rotation rate.
+ * @param squaredInputs If true, the sensitivity will be decreased for small
+ * values
+ */
+ void ArcadeDrive(GenericHID& stick, bool squaredInputs = true);
+
+ /**
+ * Arcade drive implements single stick driving.
+ *
+ * Given two joystick instances and two axis, compute the values to send to
+ * either two or four motors.
+ *
+ * @param moveStick The Joystick object that represents the
+ * forward/backward direction
+ * @param moveAxis The axis on the moveStick object to use for
+ * forwards/backwards (typically Y_AXIS)
+ * @param rotateStick The Joystick object that represents the rotation value
+ * @param rotateAxis The axis on the rotation object to use for the rotate
+ * right/left (typically X_AXIS)
+ * @param squaredInputs Setting this parameter to true increases the
+ * sensitivity at lower speeds
+ */
+ void ArcadeDrive(GenericHID* moveStick, int moveChannel,
+ GenericHID* rotateStick, int rotateChannel,
+ bool squaredInputs = true);
+
+ /**
+ * Arcade drive implements single stick driving.
+ *
+ * Given two joystick instances and two axis, compute the values to send to
+ * either two or four motors.
+ *
+ * @param moveStick The Joystick object that represents the
+ * forward/backward direction
+ * @param moveAxis The axis on the moveStick object to use for
+ * forwards/backwards (typically Y_AXIS)
+ * @param rotateStick The Joystick object that represents the rotation value
+ * @param rotateAxis The axis on the rotation object to use for the rotate
+ * right/left (typically X_AXIS)
+ * @param squaredInputs Setting this parameter to true increases the
+ * sensitivity at lower speeds
+ */
+ void ArcadeDrive(GenericHID& moveStick, int moveChannel,
+ GenericHID& rotateStick, int rotateChannel,
+ bool squaredInputs = true);
+
+ /**
+ * Arcade drive implements single stick driving.
+ *
+ * This function lets you directly provide joystick values from any source.
+ *
+ * @param moveValue The value to use for fowards/backwards
+ * @param rotateValue The value to use for the rotate right/left
+ * @param squaredInputs If set, increases the sensitivity at low speeds
+ */
+ void ArcadeDrive(double moveValue, double rotateValue,
+ bool squaredInputs = true);
+
+ /**
+ * Drive method for Mecanum wheeled robots.
+ *
+ * A method for driving with Mecanum wheeled robots. There are 4 wheels
+ * on the robot, arranged so that the front and back wheels are toed in 45
+ * degrees.
+ * When looking at the wheels from the top, the roller axles should form an X
+ * across the robot.
+ *
+ * This is designed to be directly driven by joystick axes.
+ *
+ * @param x The speed that the robot should drive in the X direction.
+ * [-1.0..1.0]
+ * @param y The speed that the robot should drive in the Y direction.
+ * This input is inverted to match the forward == -1.0 that
+ * joysticks produce. [-1.0..1.0]
+ * @param rotation The rate of rotation for the robot that is completely
+ * independent of the translation. [-1.0..1.0]
+ * @param gyroAngle The current angle reading from the gyro. Use this to
+ * implement field-oriented controls.
+ */
+ void MecanumDrive_Cartesian(double x, double y, double rotation,
+ double gyroAngle = 0.0);
+
+ /**
+ * Drive method for Mecanum wheeled robots.
+ *
+ * A method for driving with Mecanum wheeled robots. There are 4 wheels
+ * on the robot, arranged so that the front and back wheels are toed in 45
+ * degrees.
+ * When looking at the wheels from the top, the roller axles should form an X
+ * across the robot.
+ *
+ * @param magnitude The speed that the robot should drive in a given
+ * direction. [-1.0..1.0]
+ * @param direction The direction the robot should drive in degrees. The
+ * direction and maginitute are independent of the rotation
+ * rate.
+ * @param rotation The rate of rotation for the robot that is completely
+ * independent of the magnitute or direction. [-1.0..1.0]
+ */
+ void MecanumDrive_Polar(double magnitude, double direction, double rotation);
+
+ /**
+ * Holonomic Drive method for Mecanum wheeled robots.
+ *
+ * This is an alias to MecanumDrive_Polar() for backward compatability
+ *
+ * @param magnitude The speed that the robot should drive in a given
+ * direction. [-1.0..1.0]
+ * @param direction The direction the robot should drive. The direction and
+ * magnitude are independent of the rotation rate.
+ * @param rotation The rate of rotation for the robot that is completely
+ * independent of the magnitude or direction. [-1.0..1.0]
+ */
+ void HolonomicDrive(double magnitude, double direction, double rotation);
+
+ /**
+ * Set the speed of the right and left motors.
+ *
+ * This is used once an appropriate drive setup function is called such as
+ * TwoWheelDrive(). The motors are set to "leftOutput" and "rightOutput"
+ * and includes flipping the direction of one side for opposing motors.
+ *
+ * @param leftOutput The speed to send to the left side of the robot.
+ * @param rightOutput The speed to send to the right side of the robot.
+ */
+ virtual void SetLeftRightMotorOutputs(double leftOutput, double rightOutput);
+
+ /*
+ * Invert a motor direction.
+ *
+ * This is used when a motor should run in the opposite direction as the drive
+ * code would normally run it. Motors that are direct drive would be inverted,
+ * the Drive code assumes that the motors are geared with one reversal.
+ *
+ * @param motor The motor index to invert.
+ * @param isInverted True if the motor should be inverted when operated.
+ */
+ void SetInvertedMotor(MotorType motor, bool isInverted);
+
+ /**
+ * Set the turning sensitivity.
+ *
+ * This only impacts the Drive() entry-point.
+ *
+ * @param sensitivity Effectively sets the turning sensitivity (or turn radius
+ * for a given value)
+ */
+ void SetSensitivity(double sensitivity);
+
+ /**
+ * Configure the scaling factor for using RobotDrive with motor controllers in
+ * a mode other than PercentVbus.
+ *
+ * @param maxOutput Multiplied with the output percentage computed by the
+ * drive functions.
+ */
+ void SetMaxOutput(double maxOutput);
+
+ void StopMotor() override;
+ void GetDescription(wpi::raw_ostream& desc) const override;
+
+ protected:
+ /**
+ * Common function to initialize all the robot drive constructors.
+ *
+ * Create a motor safety object (the real reason for the common code) and
+ * initialize all the motor assignments. The default timeout is set for the
+ * robot drive.
+ */
+ void InitRobotDrive();
+
+ /**
+ * Limit motor values to the -1.0 to +1.0 range.
+ */
+ double Limit(double number);
+
+ /**
+ * Normalize all wheel speeds if the magnitude of any wheel is greater than
+ * 1.0.
+ */
+ void Normalize(double* wheelSpeeds);
+
+ /**
+ * Rotate a vector in Cartesian space.
+ */
+ void RotateVector(double& x, double& y, double angle);
+
+ static constexpr int kMaxNumberOfMotors = 4;
+
+ double m_sensitivity = 0.5;
+ double m_maxOutput = 1.0;
+
+ std::shared_ptr<SpeedController> m_frontLeftMotor;
+ std::shared_ptr<SpeedController> m_frontRightMotor;
+ std::shared_ptr<SpeedController> m_rearLeftMotor;
+ std::shared_ptr<SpeedController> m_rearRightMotor;
+
+ private:
+ int GetNumMotors() {
+ int motors = 0;
+ if (m_frontLeftMotor) motors++;
+ if (m_frontRightMotor) motors++;
+ if (m_rearLeftMotor) motors++;
+ if (m_rearRightMotor) motors++;
+ return motors;
+ }
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/RobotState.h b/wpilibc/src/main/native/include/frc/RobotState.h
new file mode 100644
index 0000000..6b91692
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/RobotState.h
@@ -0,0 +1,23 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+namespace frc {
+
+class RobotState {
+ public:
+ static bool IsDisabled();
+ static bool IsEnabled();
+ static bool IsOperatorControl();
+ static bool IsAutonomous();
+ static bool IsTest();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/SD540.h b/wpilibc/src/main/native/include/frc/SD540.h
new file mode 100644
index 0000000..91666b4
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/SD540.h
@@ -0,0 +1,31 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PWMSpeedController.h"
+
+namespace frc {
+
+/**
+ * Mindsensors SD540 Speed Controller.
+ */
+class SD540 : public PWMSpeedController {
+ public:
+ /**
+ * Constructor for a SD540.
+ *
+ * @param channel The PWM channel that the SD540 is attached to. 0-9 are
+ * on-board, 10-19 are on the MXP port
+ */
+ explicit SD540(int channel);
+
+ SD540(SD540&&) = default;
+ SD540& operator=(SD540&&) = default;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/SPI.h b/wpilibc/src/main/native/include/frc/SPI.h
new file mode 100644
index 0000000..88cd4d9
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/SPI.h
@@ -0,0 +1,360 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <memory>
+
+#include <hal/SPITypes.h>
+#include <wpi/ArrayRef.h>
+#include <wpi/deprecated.h>
+
+#include "frc/ErrorBase.h"
+
+namespace frc {
+
+class DigitalSource;
+
+/**
+ * SPI bus interface class.
+ *
+ * This class is intended to be used by sensor (and other SPI device) drivers.
+ * It probably should not be used directly.
+ *
+ */
+class SPI : public ErrorBase {
+ public:
+ enum Port { kOnboardCS0 = 0, kOnboardCS1, kOnboardCS2, kOnboardCS3, kMXP };
+
+ /**
+ * Constructor
+ *
+ * @param port the physical SPI port
+ */
+ explicit SPI(Port port);
+
+ ~SPI() override;
+
+ SPI(SPI&& rhs);
+ SPI& operator=(SPI&& rhs);
+
+ /**
+ * Configure the rate of the generated clock signal.
+ *
+ * The default value is 500,000Hz.
+ * The maximum value is 4,000,000Hz.
+ *
+ * @param hz The clock rate in Hertz.
+ */
+ void SetClockRate(double hz);
+
+ /**
+ * Configure the order that bits are sent and received on the wire
+ * to be most significant bit first.
+ */
+ void SetMSBFirst();
+
+ /**
+ * Configure the order that bits are sent and received on the wire
+ * to be least significant bit first.
+ */
+ void SetLSBFirst();
+
+ /**
+ * Configure that the data is stable on the leading edge and the data
+ * changes on the trailing edge.
+ */
+ void SetSampleDataOnLeadingEdge();
+
+ /**
+ * Configure that the data is stable on the trailing edge and the data
+ * changes on the leading edge.
+ */
+ void SetSampleDataOnTrailingEdge();
+
+ /**
+ * Configure that the data is stable on the falling edge and the data
+ * changes on the rising edge.
+ */
+ WPI_DEPRECATED("Use SetSampleDataOnTrailingEdge in most cases.")
+ void SetSampleDataOnFalling();
+
+ /**
+ * Configure that the data is stable on the rising edge and the data
+ * changes on the falling edge.
+ */
+ WPI_DEPRECATED("Use SetSampleDataOnLeadingEdge in most cases")
+ void SetSampleDataOnRising();
+
+ /**
+ * Configure the clock output line to be active low.
+ * This is sometimes called clock polarity high or clock idle high.
+ */
+ void SetClockActiveLow();
+
+ /**
+ * Configure the clock output line to be active high.
+ * This is sometimes called clock polarity low or clock idle low.
+ */
+ void SetClockActiveHigh();
+
+ /**
+ * Configure the chip select line to be active high.
+ */
+ void SetChipSelectActiveHigh();
+
+ /**
+ * Configure the chip select line to be active low.
+ */
+ void SetChipSelectActiveLow();
+
+ /**
+ * Write data to the slave device. Blocks until there is space in the
+ * output FIFO.
+ *
+ * If not running in output only mode, also saves the data received
+ * on the MISO input during the transfer into the receive FIFO.
+ */
+ virtual int Write(uint8_t* data, int size);
+
+ /**
+ * Read a word from the receive FIFO.
+ *
+ * Waits for the current transfer to complete if the receive FIFO is empty.
+ *
+ * If the receive FIFO is empty, there is no active transfer, and initiate
+ * is false, errors.
+ *
+ * @param initiate If true, this function pushes "0" into the transmit buffer
+ * and initiates a transfer. If false, this function assumes
+ * that data is already in the receive FIFO from a previous
+ * write.
+ */
+ virtual int Read(bool initiate, uint8_t* dataReceived, int size);
+
+ /**
+ * Perform a simultaneous read/write transaction with the device
+ *
+ * @param dataToSend The data to be written out to the device
+ * @param dataReceived Buffer to receive data from the device
+ * @param size The length of the transaction, in bytes
+ */
+ virtual int Transaction(uint8_t* dataToSend, uint8_t* dataReceived, int size);
+
+ /**
+ * Initialize automatic SPI transfer engine.
+ *
+ * Only a single engine is available, and use of it blocks use of all other
+ * chip select usage on the same physical SPI port while it is running.
+ *
+ * @param bufferSize buffer size in bytes
+ */
+ void InitAuto(int bufferSize);
+
+ /**
+ * Frees the automatic SPI transfer engine.
+ */
+ void FreeAuto();
+
+ /**
+ * Set the data to be transmitted by the engine.
+ *
+ * Up to 16 bytes are configurable, and may be followed by up to 127 zero
+ * bytes.
+ *
+ * @param dataToSend data to send (maximum 16 bytes)
+ * @param zeroSize number of zeros to send after the data
+ */
+ void SetAutoTransmitData(wpi::ArrayRef<uint8_t> dataToSend, int zeroSize);
+
+ /**
+ * Start running the automatic SPI transfer engine at a periodic rate.
+ *
+ * InitAuto() and SetAutoTransmitData() must be called before calling this
+ * function.
+ *
+ * @param period period between transfers, in seconds (us resolution)
+ */
+ void StartAutoRate(double period);
+
+ /**
+ * Start running the automatic SPI transfer engine when a trigger occurs.
+ *
+ * InitAuto() and SetAutoTransmitData() must be called before calling this
+ * function.
+ *
+ * @param source digital source for the trigger (may be an analog trigger)
+ * @param rising trigger on the rising edge
+ * @param falling trigger on the falling edge
+ */
+ void StartAutoTrigger(DigitalSource& source, bool rising, bool falling);
+
+ /**
+ * Stop running the automatic SPI transfer engine.
+ */
+ void StopAuto();
+
+ /**
+ * Force the engine to make a single transfer.
+ */
+ void ForceAutoRead();
+
+ /**
+ * Read data that has been transferred by the automatic SPI transfer engine.
+ *
+ * Transfers may be made a byte at a time, so it's necessary for the caller
+ * to handle cases where an entire transfer has not been completed.
+ *
+ * Each received data sequence consists of a timestamp followed by the
+ * received data bytes, one byte per word (in the least significant byte).
+ * The length of each received data sequence is the same as the combined
+ * size of the data and zeroSize set in SetAutoTransmitData().
+ *
+ * Blocks until numToRead words have been read or timeout expires.
+ * May be called with numToRead=0 to retrieve how many words are available.
+ *
+ * @param buffer buffer where read words are stored
+ * @param numToRead number of words to read
+ * @param timeout timeout in seconds (ms resolution)
+ * @return Number of words remaining to be read
+ */
+ int ReadAutoReceivedData(uint32_t* buffer, int numToRead, double timeout);
+
+ /**
+ * Get the number of bytes dropped by the automatic SPI transfer engine due
+ * to the receive buffer being full.
+ *
+ * @return Number of bytes dropped
+ */
+ int GetAutoDroppedCount();
+
+ /**
+ * Initialize the accumulator.
+ *
+ * @param period Time between reads
+ * @param cmd SPI command to send to request data
+ * @param xferSize SPI transfer size, in bytes
+ * @param validMask Mask to apply to received data for validity checking
+ * @param validData After valid_mask is applied, required matching value for
+ * validity checking
+ * @param dataShift Bit shift to apply to received data to get actual data
+ * value
+ * @param dataSize Size (in bits) of data field
+ * @param isSigned Is data field signed?
+ * @param bigEndian Is device big endian?
+ */
+ void InitAccumulator(double period, int cmd, int xferSize, int validMask,
+ int validValue, int dataShift, int dataSize,
+ bool isSigned, bool bigEndian);
+
+ /**
+ * Frees the accumulator.
+ */
+ void FreeAccumulator();
+
+ /**
+ * Resets the accumulator to zero.
+ */
+ void ResetAccumulator();
+
+ /**
+ * Set the center value of the accumulator.
+ *
+ * The center value is subtracted from each value before it is added to the
+ * accumulator. This is used for the center value of devices like gyros and
+ * accelerometers to make integration work and to take the device offset into
+ * account when integrating.
+ */
+ void SetAccumulatorCenter(int center);
+
+ /**
+ * Set the accumulator's deadband.
+ */
+ void SetAccumulatorDeadband(int deadband);
+
+ /**
+ * Read the last value read by the accumulator engine.
+ */
+ int GetAccumulatorLastValue() const;
+
+ /**
+ * Read the accumulated value.
+ *
+ * @return The 64-bit value accumulated since the last Reset().
+ */
+ int64_t GetAccumulatorValue() const;
+
+ /**
+ * Read the number of accumulated values.
+ *
+ * Read the count of the accumulated values since the accumulator was last
+ * Reset().
+ *
+ * @return The number of times samples from the channel were accumulated.
+ */
+ int64_t GetAccumulatorCount() const;
+
+ /**
+ * Read the average of the accumulated value.
+ *
+ * @return The accumulated average value (value / count).
+ */
+ double GetAccumulatorAverage() const;
+
+ /**
+ * Read the accumulated value and the number of accumulated values atomically.
+ *
+ * This function reads the value and count atomically.
+ * This can be used for averaging.
+ *
+ * @param value Pointer to the 64-bit accumulated output.
+ * @param count Pointer to the number of accumulation cycles.
+ */
+ void GetAccumulatorOutput(int64_t& value, int64_t& count) const;
+
+ /**
+ * Set the center value of the accumulator integrator.
+ *
+ * The center value is subtracted from each value*dt before it is added to the
+ * integrated value. This is used for the center value of devices like gyros
+ * and accelerometers to take the device offset into account when integrating.
+ */
+ void SetAccumulatorIntegratedCenter(double center);
+
+ /**
+ * Read the integrated value. This is the sum of (each value * time between
+ * values).
+ *
+ * @return The integrated value accumulated since the last Reset().
+ */
+ double GetAccumulatorIntegratedValue() const;
+
+ /**
+ * Read the average of the integrated value. This is the sum of (each value
+ * times the time between values), divided by the count.
+ *
+ * @return The average of the integrated value accumulated since the last
+ * Reset().
+ */
+ double GetAccumulatorIntegratedAverage() const;
+
+ protected:
+ HAL_SPIPort m_port = HAL_SPI_kInvalid;
+ bool m_msbFirst = false; // Default little-endian
+ bool m_sampleOnTrailing = false; // Default data updated on falling edge
+ bool m_clockIdleHigh = false; // Default clock active high
+
+ private:
+ void Init();
+
+ class Accumulator;
+ std::unique_ptr<Accumulator> m_accum;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/SampleRobot.h b/wpilibc/src/main/native/include/frc/SampleRobot.h
new file mode 100644
index 0000000..4bce0f3
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/SampleRobot.h
@@ -0,0 +1,109 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/deprecated.h>
+
+#include "frc/RobotBase.h"
+
+namespace frc {
+
+class SampleRobot : public RobotBase {
+ public:
+ /**
+ * Start a competition.
+ *
+ * This code needs to track the order of the field starting to ensure that
+ * everything happens in the right order. Repeatedly run the correct method,
+ * either Autonomous or OperatorControl or Test when the robot is enabled.
+ * After running the correct method, wait for some state to change, either the
+ * other mode starts or the robot is disabled. Then go back and wait for the
+ * robot to be enabled again.
+ */
+ void StartCompetition() override;
+
+ /**
+ * Robot-wide initialization code should go here.
+ *
+ * Users should override this method for default Robot-wide initialization
+ * which will be called when the robot is first powered on. It will be called
+ * exactly one time.
+ *
+ * Warning: the Driver Station "Robot Code" light and FMS "Robot Ready"
+ * indicators will be off until RobotInit() exits. Code in RobotInit() that
+ * waits for enable will cause the robot to never indicate that the code is
+ * ready, causing the robot to be bypassed in a match.
+ */
+ virtual void RobotInit();
+
+ /**
+ * Disabled should go here.
+ *
+ * Programmers should override this method to run code that should run while
+ * the field is disabled.
+ */
+ virtual void Disabled();
+
+ /**
+ * Autonomous should go here.
+ *
+ * Programmers should override this method to run code that should run while
+ * the field is in the autonomous period. This will be called once each time
+ * the robot enters the autonomous state.
+ */
+ virtual void Autonomous();
+
+ /**
+ * Operator control (tele-operated) code should go here.
+ *
+ * Programmers should override this method to run code that should run while
+ * the field is in the Operator Control (tele-operated) period. This is called
+ * once each time the robot enters the teleop state.
+ */
+ virtual void OperatorControl();
+
+ /**
+ * Test program should go here.
+ *
+ * Programmers should override this method to run code that executes while the
+ * robot is in test mode. This will be called once whenever the robot enters
+ * test mode
+ */
+ virtual void Test();
+
+ /**
+ * Robot main program for free-form programs.
+ *
+ * This should be overridden by user subclasses if the intent is to not use
+ * the Autonomous() and OperatorControl() methods. In that case, the program
+ * is responsible for sensing when to run the autonomous and operator control
+ * functions in their program.
+ *
+ * This method will be called immediately after the constructor is called. If
+ * it has not been overridden by a user subclass (i.e. the default version
+ * runs), then the Autonomous() and OperatorControl() methods will be called.
+ */
+ virtual void RobotMain();
+
+ protected:
+ WPI_DEPRECATED(
+ "WARNING: While it may look like a good choice to use for your code if "
+ "you're inexperienced, don't. Unless you know what you are doing, "
+ "complex code will be much more difficult under this system. Use "
+ "TimedRobot or Command-Based instead.")
+ SampleRobot();
+ virtual ~SampleRobot() = default;
+
+ SampleRobot(SampleRobot&&) = default;
+ SampleRobot& operator=(SampleRobot&&) = default;
+
+ private:
+ bool m_robotMainOverridden = true;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/SensorUtil.h b/wpilibc/src/main/native/include/frc/SensorUtil.h
new file mode 100644
index 0000000..a38b542
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/SensorUtil.h
@@ -0,0 +1,117 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+/**
+ * Stores most recent status information as well as containing utility functions
+ * for checking channels and error processing.
+ */
+class SensorUtil final {
+ public:
+ /**
+ * Get the number of the default solenoid module.
+ *
+ * @return The number of the default solenoid module.
+ */
+ static int GetDefaultSolenoidModule();
+
+ /**
+ * Check that the solenoid module number is valid. module numbers are 0-based
+ *
+ * @return Solenoid module is valid and present
+ */
+ static bool CheckSolenoidModule(int moduleNumber);
+
+ /**
+ * Check that the digital channel number is valid.
+ *
+ * Verify that the channel number is one of the legal channel numbers. Channel
+ * numbers are 0-based.
+ *
+ * @return Digital channel is valid
+ */
+ static bool CheckDigitalChannel(int channel);
+
+ /**
+ * Check that the relay channel number is valid.
+ *
+ * Verify that the channel number is one of the legal channel numbers. Channel
+ * numbers are 0-based.
+ *
+ * @return Relay channel is valid
+ */
+ static bool CheckRelayChannel(int channel);
+
+ /**
+ * Check that the digital channel number is valid.
+ *
+ * Verify that the channel number is one of the legal channel numbers. Channel
+ * numbers are 0-based.
+ *
+ * @return PWM channel is valid
+ */
+ static bool CheckPWMChannel(int channel);
+
+ /**
+ * Check that the analog input number is value.
+ *
+ * Verify that the analog input number is one of the legal channel numbers.
+ * Channel numbers are 0-based.
+ *
+ * @return Analog channel is valid
+ */
+ static bool CheckAnalogInputChannel(int channel);
+
+ /**
+ * Check that the analog output number is valid.
+ *
+ * Verify that the analog output number is one of the legal channel numbers.
+ * Channel numbers are 0-based.
+ *
+ * @return Analog channel is valid
+ */
+ static bool CheckAnalogOutputChannel(int channel);
+
+ /**
+ * Verify that the solenoid channel number is within limits.
+ *
+ * @return Solenoid channel is valid
+ */
+ static bool CheckSolenoidChannel(int channel);
+
+ /**
+ * Verify that the power distribution channel number is within limits.
+ *
+ * @return PDP channel is valid
+ */
+ static bool CheckPDPChannel(int channel);
+
+ /**
+ * Verify that the PDP module number is within limits. module numbers are
+ * 0-based
+ *
+ * @return PDP module is valid
+ */
+ static bool CheckPDPModule(int module);
+
+ static const int kDigitalChannels;
+ static const int kAnalogInputs;
+ static const int kAnalogOutputs;
+ static const int kSolenoidChannels;
+ static const int kSolenoidModules;
+ static const int kPwmChannels;
+ static const int kRelayChannels;
+ static const int kPDPChannels;
+
+ private:
+ SensorUtil() = default;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/SerialPort.h b/wpilibc/src/main/native/include/frc/SerialPort.h
new file mode 100644
index 0000000..e9e38ef
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/SerialPort.h
@@ -0,0 +1,223 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <string>
+
+#include <wpi/StringRef.h>
+#include <wpi/Twine.h>
+#include <wpi/deprecated.h>
+
+#include "frc/ErrorBase.h"
+
+namespace frc {
+
+/**
+ * Driver for the RS-232 serial port on the roboRIO.
+ *
+ * The current implementation uses the VISA formatted I/O mode. This means that
+ * all traffic goes through the fomatted buffers. This allows the intermingled
+ * use of Printf(), Scanf(), and the raw buffer accessors Read() and Write().
+ *
+ * More information can be found in the NI-VISA User Manual here:
+ * http://www.ni.com/pdf/manuals/370423a.pdf
+ * and the NI-VISA Programmer's Reference Manual here:
+ * http://www.ni.com/pdf/manuals/370132c.pdf
+ */
+class SerialPort : public ErrorBase {
+ public:
+ enum Parity {
+ kParity_None = 0,
+ kParity_Odd = 1,
+ kParity_Even = 2,
+ kParity_Mark = 3,
+ kParity_Space = 4
+ };
+
+ enum StopBits {
+ kStopBits_One = 10,
+ kStopBits_OnePointFive = 15,
+ kStopBits_Two = 20
+ };
+
+ enum FlowControl {
+ kFlowControl_None = 0,
+ kFlowControl_XonXoff = 1,
+ kFlowControl_RtsCts = 2,
+ kFlowControl_DtrDsr = 4
+ };
+
+ enum WriteBufferMode { kFlushOnAccess = 1, kFlushWhenFull = 2 };
+
+ enum Port { kOnboard = 0, kMXP = 1, kUSB = 2, kUSB1 = 2, kUSB2 = 3 };
+
+ /**
+ * Create an instance of a Serial Port class.
+ *
+ * @param baudRate The baud rate to configure the serial port.
+ * @param port The physical port to use
+ * @param dataBits The number of data bits per transfer. Valid values are
+ * between 5 and 8 bits.
+ * @param parity Select the type of parity checking to use.
+ * @param stopBits The number of stop bits to use as defined by the enum
+ * StopBits.
+ */
+ SerialPort(int baudRate, Port port = kOnboard, int dataBits = 8,
+ Parity parity = kParity_None, StopBits stopBits = kStopBits_One);
+
+ /**
+ * Create an instance of a Serial Port class.
+ *
+ * @param baudRate The baud rate to configure the serial port.
+ * @param port The physical port to use
+ * @param portName The direct port name to use
+ * @param dataBits The number of data bits per transfer. Valid values are
+ * between 5 and 8 bits.
+ * @param parity Select the type of parity checking to use.
+ * @param stopBits The number of stop bits to use as defined by the enum
+ * StopBits.
+ */
+ WPI_DEPRECATED("Will be removed for 2020")
+ SerialPort(int baudRate, const wpi::Twine& portName, Port port = kOnboard,
+ int dataBits = 8, Parity parity = kParity_None,
+ StopBits stopBits = kStopBits_One);
+
+ ~SerialPort();
+
+ SerialPort(SerialPort&& rhs);
+ SerialPort& operator=(SerialPort&& rhs);
+
+ /**
+ * Set the type of flow control to enable on this port.
+ *
+ * By default, flow control is disabled.
+ */
+ void SetFlowControl(FlowControl flowControl);
+
+ /**
+ * Enable termination and specify the termination character.
+ *
+ * Termination is currently only implemented for receive.
+ * When the the terminator is recieved, the Read() or Scanf() will return
+ * fewer bytes than requested, stopping after the terminator.
+ *
+ * @param terminator The character to use for termination.
+ */
+ void EnableTermination(char terminator = '\n');
+
+ /**
+ * Disable termination behavior.
+ */
+ void DisableTermination();
+
+ /**
+ * Get the number of bytes currently available to read from the serial port.
+ *
+ * @return The number of bytes available to read
+ */
+ int GetBytesReceived();
+
+ /**
+ * Read raw bytes out of the buffer.
+ *
+ * @param buffer Pointer to the buffer to store the bytes in.
+ * @param count The maximum number of bytes to read.
+ * @return The number of bytes actually read into the buffer.
+ */
+ int Read(char* buffer, int count);
+
+ /**
+ * Write raw bytes to the buffer.
+ *
+ * @param buffer Pointer to the buffer to read the bytes from.
+ * @param count The maximum number of bytes to write.
+ * @return The number of bytes actually written into the port.
+ */
+ int Write(const char* buffer, int count);
+
+ /**
+ * Write raw bytes to the buffer.
+ *
+ * Use Write({data, len}) to get a buffer that is shorter than the length of
+ * the string.
+ *
+ * @param buffer StringRef to the buffer to read the bytes from.
+ * @return The number of bytes actually written into the port.
+ */
+ int Write(wpi::StringRef buffer);
+
+ /**
+ * Configure the timeout of the serial port.
+ *
+ * This defines the timeout for transactions with the hardware.
+ * It will affect reads and very large writes.
+ *
+ * @param timeout The number of seconds to to wait for I/O.
+ */
+ void SetTimeout(double timeout);
+
+ /**
+ * Specify the size of the input buffer.
+ *
+ * Specify the amount of data that can be stored before data
+ * from the device is returned to Read or Scanf. If you want
+ * data that is recieved to be returned immediately, set this to 1.
+ *
+ * It the buffer is not filled before the read timeout expires, all
+ * data that has been received so far will be returned.
+ *
+ * @param size The read buffer size.
+ */
+ void SetReadBufferSize(int size);
+
+ /**
+ * Specify the size of the output buffer.
+ *
+ * Specify the amount of data that can be stored before being
+ * transmitted to the device.
+ *
+ * @param size The write buffer size.
+ */
+ void SetWriteBufferSize(int size);
+
+ /**
+ * Specify the flushing behavior of the output buffer.
+ *
+ * When set to kFlushOnAccess, data is synchronously written to the serial
+ * port after each call to either Printf() or Write().
+ *
+ * When set to kFlushWhenFull, data will only be written to the serial port
+ * when the buffer is full or when Flush() is called.
+ *
+ * @param mode The write buffer mode.
+ */
+ void SetWriteBufferMode(WriteBufferMode mode);
+
+ /**
+ * Force the output buffer to be written to the port.
+ *
+ * This is used when SetWriteBufferMode() is set to kFlushWhenFull to force a
+ * flush before the buffer is full.
+ */
+ void Flush();
+
+ /**
+ * Reset the serial port driver to a known state.
+ *
+ * Empty the transmit and receive buffers in the device and formatted I/O.
+ */
+ void Reset();
+
+ private:
+ int m_resourceManagerHandle = 0;
+ int m_portHandle = 0;
+ bool m_consoleModeEnabled = false;
+ Port m_port = kOnboard;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Servo.h b/wpilibc/src/main/native/include/frc/Servo.h
new file mode 100644
index 0000000..ae5c599
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Servo.h
@@ -0,0 +1,111 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PWM.h"
+#include "frc/SpeedController.h"
+
+namespace frc {
+
+/**
+ * Standard hobby style servo.
+ *
+ * The range parameters default to the appropriate values for the Hitec HS-322HD
+ * servo provided in the FIRST Kit of Parts in 2008.
+ */
+class Servo : public PWM {
+ public:
+ /**
+ * @param channel The PWM channel to which the servo is attached. 0-9 are
+ * on-board, 10-19 are on the MXP port
+ */
+ explicit Servo(int channel);
+
+ Servo(Servo&&) = default;
+ Servo& operator=(Servo&&) = default;
+
+ /**
+ * Set the servo position.
+ *
+ * Servo values range from 0.0 to 1.0 corresponding to the range of full left
+ * to full right.
+ *
+ * @param value Position from 0.0 to 1.0.
+ */
+ void Set(double value);
+
+ /**
+ * Set the servo to offline.
+ *
+ * Set the servo raw value to 0 (undriven)
+ */
+ void SetOffline();
+
+ /**
+ * Get the servo position.
+ *
+ * Servo values range from 0.0 to 1.0 corresponding to the range of full left
+ * to full right.
+ *
+ * @return Position from 0.0 to 1.0.
+ */
+ double Get() const;
+
+ /**
+ * Set the servo angle.
+ *
+ * Assume that the servo angle is linear with respect to the PWM value (big
+ * assumption, need to test).
+ *
+ * Servo angles that are out of the supported range of the servo simply
+ * "saturate" in that direction. In other words, if the servo has a range of
+ * (X degrees to Y degrees) than angles of less than X result in an angle of
+ * X being set and angles of more than Y degrees result in an angle of Y being
+ * set.
+ *
+ * @param degrees The angle in degrees to set the servo.
+ */
+ void SetAngle(double angle);
+
+ /**
+ * Get the servo angle.
+ *
+ * Assume that the servo angle is linear with respect to the PWM value (big
+ * assumption, need to test).
+ *
+ * @return The angle in degrees to which the servo is set.
+ */
+ double GetAngle() const;
+
+ /**
+ * Get the maximum angle of the servo.
+ *
+ * @return The maximum angle of the servo in degrees.
+ */
+ double GetMaxAngle() const;
+
+ /**
+ * Get the minimum angle of the servo.
+ *
+ * @return The minimum angle of the servo in degrees.
+ */
+ double GetMinAngle() const;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ double GetServoAngleRange() const;
+
+ static constexpr double kMaxServoAngle = 180.0;
+ static constexpr double kMinServoAngle = 0.0;
+
+ static constexpr double kDefaultMaxServoPWM = 2.4;
+ static constexpr double kDefaultMinServoPWM = .6;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Solenoid.h b/wpilibc/src/main/native/include/frc/Solenoid.h
new file mode 100644
index 0000000..8a90b26
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Solenoid.h
@@ -0,0 +1,97 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <hal/Types.h>
+
+#include "frc/SolenoidBase.h"
+
+namespace frc {
+
+/**
+ * Solenoid class for running high voltage Digital Output (PCM).
+ *
+ * The Solenoid class is typically used for pneumatics solenoids, but could be
+ * used for any device within the current spec of the PCM.
+ */
+class Solenoid : public SolenoidBase {
+ public:
+ /**
+ * Constructor using the default PCM ID (0).
+ *
+ * @param channel The channel on the PCM to control (0..7).
+ */
+ explicit Solenoid(int channel);
+
+ /**
+ * Constructor.
+ *
+ * @param moduleNumber The CAN ID of the PCM the solenoid is attached to
+ * @param channel The channel on the PCM to control (0..7).
+ */
+ Solenoid(int moduleNumber, int channel);
+
+ ~Solenoid() override;
+
+ Solenoid(Solenoid&& rhs);
+ Solenoid& operator=(Solenoid&& rhs);
+
+ /**
+ * Set the value of a solenoid.
+ *
+ * @param on Turn the solenoid output off or on.
+ */
+ virtual void Set(bool on);
+
+ /**
+ * Read the current value of the solenoid.
+ *
+ * @return The current value of the solenoid.
+ */
+ virtual bool Get() const;
+
+ /**
+ * Check if solenoid is blacklisted.
+ *
+ * If a solenoid is shorted, it is added to the blacklist and
+ * disabled until power cycle, or until faults are cleared.
+ *
+ * @see ClearAllPCMStickyFaults()
+ *
+ * @return If solenoid is disabled due to short.
+ */
+ bool IsBlackListed() const;
+
+ /**
+ * Set the pulse duration in the PCM. This is used in conjunction with
+ * the startPulse method to allow the PCM to control the timing of a pulse.
+ * The timing can be controlled in 0.01 second increments.
+ *
+ * @param durationSeconds The duration of the pulse, from 0.01 to 2.55
+ * seconds.
+ *
+ * @see startPulse()
+ */
+ void SetPulseDuration(double durationSeconds);
+
+ /**
+ * Trigger the PCM to generate a pulse of the duration set in
+ * setPulseDuration.
+ *
+ * @see setPulseDuration()
+ */
+ void StartPulse();
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ HAL_SolenoidHandle m_solenoidHandle = HAL_kInvalidHandle;
+ int m_channel; // The channel on the module to control
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/SolenoidBase.h b/wpilibc/src/main/native/include/frc/SolenoidBase.h
new file mode 100644
index 0000000..fe9f32e
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/SolenoidBase.h
@@ -0,0 +1,128 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/ErrorBase.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * SolenoidBase class is the common base class for the Solenoid and
+ * DoubleSolenoid classes.
+ */
+class SolenoidBase : public ErrorBase, public SendableBase {
+ public:
+ /**
+ * Read all 8 solenoids as a single byte
+ *
+ * @param module the module to read from
+ * @return The current value of all 8 solenoids on the module.
+ */
+ static int GetAll(int module);
+
+ /**
+ * Read all 8 solenoids as a single byte
+ *
+ * @return The current value of all 8 solenoids on the module.
+ */
+ int GetAll() const;
+
+ /**
+ * Reads complete solenoid blacklist for all 8 solenoids as a single byte.
+ *
+ * If a solenoid is shorted, it is added to the blacklist and
+ * disabled until power cycle, or until faults are cleared.
+ * @see ClearAllPCMStickyFaults()
+ *
+ * @param module the module to read from
+ * @return The solenoid blacklist of all 8 solenoids on the module.
+ */
+ static int GetPCMSolenoidBlackList(int module);
+
+ /**
+ * Reads complete solenoid blacklist for all 8 solenoids as a single byte.
+ *
+ * If a solenoid is shorted, it is added to the blacklist and
+ * disabled until power cycle, or until faults are cleared.
+ * @see ClearAllPCMStickyFaults()
+ *
+ * @return The solenoid blacklist of all 8 solenoids on the module.
+ */
+ int GetPCMSolenoidBlackList() const;
+
+ /**
+ * @param module the module to read from
+ * @return true if PCM sticky fault is set : The common highside solenoid
+ * voltage rail is too low, most likely a solenoid channel is shorted.
+ */
+ static bool GetPCMSolenoidVoltageStickyFault(int module);
+
+ /**
+ * @return true if PCM sticky fault is set : The common highside solenoid
+ * voltage rail is too low, most likely a solenoid channel is shorted.
+ */
+ bool GetPCMSolenoidVoltageStickyFault() const;
+
+ /**
+ * @param module the module to read from
+ * @return true if PCM is in fault state : The common highside solenoid
+ * voltage rail is too low, most likely a solenoid channel is shorted.
+ */
+ static bool GetPCMSolenoidVoltageFault(int module);
+
+ /**
+ * @return true if PCM is in fault state : The common highside solenoid
+ * voltage rail is too low, most likely a solenoid channel is shorted.
+ */
+ bool GetPCMSolenoidVoltageFault() const;
+
+ /**
+ * Clear ALL sticky faults inside PCM that Compressor is wired to.
+ *
+ * If a sticky fault is set, then it will be persistently cleared. Compressor
+ * drive maybe momentarily disable while flags are being cleared. Care should
+ * be taken to not call this too frequently, otherwise normal compressor
+ * functionality may be prevented.
+ *
+ * If no sticky faults are set then this call will have no effect.
+ *
+ * @param module the module to read from
+ */
+ static void ClearAllPCMStickyFaults(int module);
+
+ /**
+ * Clear ALL sticky faults inside PCM that Compressor is wired to.
+ *
+ * If a sticky fault is set, then it will be persistently cleared. Compressor
+ * drive maybe momentarily disable while flags are being cleared. Care should
+ * be taken to not call this too frequently, otherwise normal compressor
+ * functionality may be prevented.
+ *
+ * If no sticky faults are set then this call will have no effect.
+ */
+ void ClearAllPCMStickyFaults();
+
+ protected:
+ /**
+ * Constructor.
+ *
+ * @param moduleNumber The CAN PCM ID.
+ */
+ explicit SolenoidBase(int pcmID);
+
+ SolenoidBase(SolenoidBase&&) = default;
+ SolenoidBase& operator=(SolenoidBase&&) = default;
+
+ static constexpr int m_maxModules = 63;
+ static constexpr int m_maxPorts = 8;
+
+ int m_moduleNumber; // PCM module number
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Spark.h b/wpilibc/src/main/native/include/frc/Spark.h
new file mode 100644
index 0000000..640696f
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Spark.h
@@ -0,0 +1,31 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PWMSpeedController.h"
+
+namespace frc {
+
+/**
+ * REV Robotics Speed Controller.
+ */
+class Spark : public PWMSpeedController {
+ public:
+ /**
+ * Constructor for a Spark.
+ *
+ * @param channel The PWM channel that the Spark is attached to. 0-9 are
+ * on-board, 10-19 are on the MXP port
+ */
+ explicit Spark(int channel);
+
+ Spark(Spark&&) = default;
+ Spark& operator=(Spark&&) = default;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/SpeedController.h b/wpilibc/src/main/native/include/frc/SpeedController.h
new file mode 100644
index 0000000..49a828b
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/SpeedController.h
@@ -0,0 +1,60 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PIDOutput.h"
+
+namespace frc {
+
+/**
+ * Interface for speed controlling devices.
+ */
+class SpeedController : public PIDOutput {
+ public:
+ virtual ~SpeedController() = default;
+
+ /**
+ * Common interface for setting the speed of a speed controller.
+ *
+ * @param speed The speed to set. Value should be between -1.0 and 1.0.
+ */
+ virtual void Set(double speed) = 0;
+
+ /**
+ * Common interface for getting the current set speed of a speed controller.
+ *
+ * @return The current set speed. Value is between -1.0 and 1.0.
+ */
+ virtual double Get() const = 0;
+
+ /**
+ * Common interface for inverting direction of a speed controller.
+ *
+ * @param isInverted The state of inversion, true is inverted.
+ */
+ virtual void SetInverted(bool isInverted) = 0;
+
+ /**
+ * Common interface for returning the inversion state of a speed controller.
+ *
+ * @return isInverted The state of inversion, true is inverted.
+ */
+ virtual bool GetInverted() const = 0;
+
+ /**
+ * Common interface for disabling a motor.
+ */
+ virtual void Disable() = 0;
+
+ /**
+ * Common interface to stop the motor until Set is called again.
+ */
+ virtual void StopMotor() = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/SpeedControllerGroup.h b/wpilibc/src/main/native/include/frc/SpeedControllerGroup.h
new file mode 100644
index 0000000..3f0c699
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/SpeedControllerGroup.h
@@ -0,0 +1,45 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <functional>
+#include <vector>
+
+#include "frc/SpeedController.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class SpeedControllerGroup : public SendableBase, public SpeedController {
+ public:
+ template <class... SpeedControllers>
+ explicit SpeedControllerGroup(SpeedController& speedController,
+ SpeedControllers&... speedControllers);
+ ~SpeedControllerGroup() override = default;
+
+ SpeedControllerGroup(SpeedControllerGroup&&) = default;
+ SpeedControllerGroup& operator=(SpeedControllerGroup&&) = default;
+
+ void Set(double speed) override;
+ double Get() const override;
+ void SetInverted(bool isInverted) override;
+ bool GetInverted() const override;
+ void Disable() override;
+ void StopMotor() override;
+ void PIDWrite(double output) override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ bool m_isInverted = false;
+ std::vector<std::reference_wrapper<SpeedController>> m_speedControllers;
+};
+
+} // namespace frc
+
+#include "frc/SpeedControllerGroup.inc"
diff --git a/wpilibc/src/main/native/include/frc/SpeedControllerGroup.inc b/wpilibc/src/main/native/include/frc/SpeedControllerGroup.inc
new file mode 100644
index 0000000..ba4b766
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/SpeedControllerGroup.inc
@@ -0,0 +1,23 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+template <class... SpeedControllers>
+SpeedControllerGroup::SpeedControllerGroup(
+ SpeedController& speedController, SpeedControllers&... speedControllers)
+ : m_speedControllers{speedController, speedControllers...} {
+ for (auto& speedController : m_speedControllers)
+ AddChild(&speedController.get());
+ static int instances = 0;
+ ++instances;
+ SetName("SpeedControllerGroup", instances);
+}
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Talon.h b/wpilibc/src/main/native/include/frc/Talon.h
new file mode 100644
index 0000000..9a5400f
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Talon.h
@@ -0,0 +1,31 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PWMSpeedController.h"
+
+namespace frc {
+
+/**
+ * Cross the Road Electronics (CTRE) Talon and Talon SR Speed Controller.
+ */
+class Talon : public PWMSpeedController {
+ public:
+ /**
+ * Constructor for a Talon (original or Talon SR).
+ *
+ * @param channel The PWM channel number that the Talon is attached to. 0-9
+ * are on-board, 10-19 are on the MXP port
+ */
+ explicit Talon(int channel);
+
+ Talon(Talon&&) = default;
+ Talon& operator=(Talon&&) = default;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Threads.h b/wpilibc/src/main/native/include/frc/Threads.h
new file mode 100644
index 0000000..3c44961
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Threads.h
@@ -0,0 +1,58 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <thread>
+
+namespace frc {
+
+/**
+ * Get the thread priority for the specified thread.
+ *
+ * @param thread Reference to the thread to get the priority for.
+ * @param isRealTime Set to true if thread is realtime, otherwise false.
+ * @return The current thread priority. Scaled 1-99, with 1 being highest.
+ */
+int GetThreadPriority(std::thread& thread, bool* isRealTime);
+
+/**
+ * Get the thread priority for the current thread
+ *
+ * @param isRealTime Set to true if thread is realtime, otherwise false.
+ * @return The current thread priority. Scaled 1-99.
+ */
+int GetCurrentThreadPriority(bool* isRealTime);
+
+/**
+ * Sets the thread priority for the specified thread
+ *
+ * @param thread Reference to the thread to set the priority of.
+ * @param realTime Set to true to set a realtime priority, false for standard
+ * priority.
+ * @param priority Priority to set the thread to. Scaled 1-99, with 1 being
+ * highest. On RoboRIO, priority is ignored for non realtime
+ * setting.
+ *
+ * @return The success state of setting the priority
+ */
+bool SetThreadPriority(std::thread& thread, bool realTime, int priority);
+
+/**
+ * Sets the thread priority for the current thread
+ *
+ * @param realTime Set to true to set a realtime priority, false for standard
+ * priority.
+ * @param priority Priority to set the thread to. Scaled 1-99, with 1 being
+ * highest. On RoboRIO, priority is ignored for non realtime
+ * setting.
+ *
+ * @return The success state of setting the priority
+ */
+bool SetCurrentThreadPriority(bool realTime, int priority);
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/TimedRobot.h b/wpilibc/src/main/native/include/frc/TimedRobot.h
new file mode 100644
index 0000000..a6da5ee
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/TimedRobot.h
@@ -0,0 +1,64 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <hal/Types.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/IterativeRobotBase.h"
+
+namespace frc {
+
+/**
+ * TimedRobot implements the IterativeRobotBase robot program framework.
+ *
+ * The TimedRobot class is intended to be subclassed by a user creating a
+ * robot program.
+ *
+ * Periodic() functions from the base class are called on an interval by a
+ * Notifier instance.
+ */
+class TimedRobot : public IterativeRobotBase, public ErrorBase {
+ public:
+ static constexpr double kDefaultPeriod = 0.02;
+
+ /**
+ * Provide an alternate "main loop" via StartCompetition().
+ */
+ void StartCompetition() override;
+
+ /**
+ * Get the time period between calls to Periodic() functions.
+ */
+ double GetPeriod() const;
+
+ /**
+ * Constructor for TimedRobot.
+ *
+ * @param period Period in seconds.
+ */
+ explicit TimedRobot(double period = kDefaultPeriod);
+
+ ~TimedRobot() override;
+
+ TimedRobot(TimedRobot&& rhs);
+ TimedRobot& operator=(TimedRobot&& rhs);
+
+ private:
+ HAL_NotifierHandle m_notifier{0};
+
+ // The absolute expiration time
+ double m_expirationTime = 0;
+
+ /**
+ * Update the HAL alarm time.
+ */
+ void UpdateAlarm();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Timer.h b/wpilibc/src/main/native/include/frc/Timer.h
new file mode 100644
index 0000000..f665c83
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Timer.h
@@ -0,0 +1,153 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/deprecated.h>
+#include <wpi/mutex.h>
+
+#include "frc/Base.h"
+
+namespace frc {
+
+using TimerInterruptHandler = void (*)(void* param);
+
+/**
+ * Pause the task for a specified time.
+ *
+ * Pause the execution of the program for a specified period of time given in
+ * seconds. Motors will continue to run at their last assigned values, and
+ * sensors will continue to update. Only the task containing the wait will pause
+ * until the wait time is expired.
+ *
+ * @param seconds Length of time to pause, in seconds.
+ */
+void Wait(double seconds);
+
+/**
+ * Return the FPGA system clock time in seconds.
+ *
+ * This is deprecated and just forwards to Timer::GetFPGATimestamp().
+ *
+ * @return Robot running time in seconds.
+ */
+WPI_DEPRECATED("Use Timer::GetFPGATimestamp() instead.")
+double GetClock();
+
+/**
+ * @brief Gives real-time clock system time with nanosecond resolution
+ * @return The time, just in case you want the robot to start autonomous at 8pm
+ * on Saturday.
+ */
+double GetTime();
+
+/**
+ * Timer objects measure accumulated time in seconds.
+ *
+ * The timer object functions like a stopwatch. It can be started, stopped, and
+ * cleared. When the timer is running its value counts up in seconds. When
+ * stopped, the timer holds the current value. The implementation simply records
+ * the time when started and subtracts the current time whenever the value is
+ * requested.
+ */
+class Timer {
+ public:
+ /**
+ * Create a new timer object.
+ *
+ * Create a new timer object and reset the time to zero. The timer is
+ * initially not running and must be started.
+ */
+ Timer();
+
+ virtual ~Timer() = default;
+
+ Timer(Timer&&) = default;
+ Timer& operator=(Timer&&) = default;
+
+ /**
+ * Get the current time from the timer. If the clock is running it is derived
+ * from the current system clock the start time stored in the timer class. If
+ * the clock is not running, then return the time when it was last stopped.
+ *
+ * @return Current time value for this timer in seconds
+ */
+ double Get() const;
+
+ /**
+ * Reset the timer by setting the time to 0.
+ *
+ * Make the timer startTime the current time so new requests will be relative
+ * to now.
+ */
+ void Reset();
+
+ /**
+ * Start the timer running.
+ *
+ * Just set the running flag to true indicating that all time requests should
+ * be relative to the system clock.
+ */
+ void Start();
+
+ /**
+ * Stop the timer.
+ *
+ * This computes the time as of now and clears the running flag, causing all
+ * subsequent time requests to be read from the accumulated time rather than
+ * looking at the system clock.
+ */
+ void Stop();
+
+ /**
+ * Check if the period specified has passed and if it has, advance the start
+ * time by that period. This is useful to decide if it's time to do periodic
+ * work without drifting later by the time it took to get around to checking.
+ *
+ * @param period The period to check for (in seconds).
+ * @return True if the period has passed.
+ */
+ bool HasPeriodPassed(double period);
+
+ /**
+ * Return the FPGA system clock time in seconds.
+ *
+ * Return the time from the FPGA hardware clock in seconds since the FPGA
+ * started. Rolls over after 71 minutes.
+ *
+ * @returns Robot running time in seconds.
+ */
+ static double GetFPGATimestamp();
+
+ /**
+ * Return the approximate match time.
+ *
+ * The FMS does not send an official match time to the robots, but does send
+ * an approximate match time. The value will count down the time remaining in
+ * the current period (auto or teleop).
+ *
+ * Warning: This is not an official time (so it cannot be used to dispute ref
+ * calls or guarantee that a function will trigger before the match ends).
+ *
+ * The Practice Match function of the DS approximates the behavior seen on the
+ * field.
+ *
+ * @return Time remaining in current match period (auto or teleop)
+ */
+ static double GetMatchTime();
+
+ // The time, in seconds, at which the 32-bit FPGA timestamp rolls over to 0
+ static const double kRolloverTime;
+
+ private:
+ double m_startTime = 0.0;
+ double m_accumulatedTime = 0.0;
+ bool m_running = false;
+ mutable wpi::mutex m_mutex;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Ultrasonic.h b/wpilibc/src/main/native/include/frc/Ultrasonic.h
new file mode 100644
index 0000000..82ae6ca
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Ultrasonic.h
@@ -0,0 +1,231 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <atomic>
+#include <memory>
+#include <thread>
+#include <vector>
+
+#include "frc/Counter.h"
+#include "frc/ErrorBase.h"
+#include "frc/PIDSource.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class DigitalInput;
+class DigitalOutput;
+
+/**
+ * Ultrasonic rangefinder class.
+ *
+ * The Ultrasonic rangefinder measures absolute distance based on the round-trip
+ * time of a ping generated by the controller. These sensors use two
+ * transducers, a speaker and a microphone both tuned to the ultrasonic range. A
+ * common ultrasonic sensor, the Daventech SRF04 requires a short pulse to be
+ * generated on a digital channel. This causes the chirp to be emitted. A second
+ * line becomes high as the ping is transmitted and goes low when the echo is
+ * received. The time that the line is high determines the round trip distance
+ * (time of flight).
+ */
+class Ultrasonic : public ErrorBase, public SendableBase, public PIDSource {
+ public:
+ enum DistanceUnit { kInches = 0, kMilliMeters = 1 };
+
+ /**
+ * Create an instance of the Ultrasonic Sensor.
+ *
+ * This is designed to support the Daventech SRF04 and Vex ultrasonic sensors.
+ *
+ * @param pingChannel The digital output channel that sends the pulse to
+ * initiate the sensor sending the ping.
+ * @param echoChannel The digital input channel that receives the echo. The
+ * length of time that the echo is high represents the
+ * round trip time of the ping, and the distance.
+ * @param units The units returned in either kInches or kMilliMeters
+ */
+ Ultrasonic(int pingChannel, int echoChannel, DistanceUnit units = kInches);
+
+ /**
+ * Create an instance of an Ultrasonic Sensor from a DigitalInput for the echo
+ * channel and a DigitalOutput for the ping channel.
+ *
+ * @param pingChannel The digital output object that starts the sensor doing a
+ * ping. Requires a 10uS pulse to start.
+ * @param echoChannel The digital input object that times the return pulse to
+ * determine the range.
+ * @param units The units returned in either kInches or kMilliMeters
+ */
+ Ultrasonic(DigitalOutput* pingChannel, DigitalInput* echoChannel,
+ DistanceUnit units = kInches);
+
+ /**
+ * Create an instance of an Ultrasonic Sensor from a DigitalInput for the echo
+ * channel and a DigitalOutput for the ping channel.
+ *
+ * @param pingChannel The digital output object that starts the sensor doing a
+ * ping. Requires a 10uS pulse to start.
+ * @param echoChannel The digital input object that times the return pulse to
+ * determine the range.
+ * @param units The units returned in either kInches or kMilliMeters
+ */
+ Ultrasonic(DigitalOutput& pingChannel, DigitalInput& echoChannel,
+ DistanceUnit units = kInches);
+
+ /**
+ * Create an instance of an Ultrasonic Sensor from a DigitalInput for the echo
+ * channel and a DigitalOutput for the ping channel.
+ *
+ * @param pingChannel The digital output object that starts the sensor doing a
+ * ping. Requires a 10uS pulse to start.
+ * @param echoChannel The digital input object that times the return pulse to
+ * determine the range.
+ * @param units The units returned in either kInches or kMilliMeters
+ */
+ Ultrasonic(std::shared_ptr<DigitalOutput> pingChannel,
+ std::shared_ptr<DigitalInput> echoChannel,
+ DistanceUnit units = kInches);
+
+ ~Ultrasonic() override;
+
+ Ultrasonic(Ultrasonic&&) = default;
+ Ultrasonic& operator=(Ultrasonic&&) = default;
+
+ /**
+ * Single ping to ultrasonic sensor.
+ *
+ * Send out a single ping to the ultrasonic sensor. This only works if
+ * automatic (round robin) mode is disabled. A single ping is sent out, and
+ * the counter should count the semi-period when it comes in. The counter is
+ * reset to make the current value invalid.
+ */
+ void Ping();
+
+ /**
+ * Check if there is a valid range measurement.
+ *
+ * The ranges are accumulated in a counter that will increment on each edge of
+ * the echo (return) signal. If the count is not at least 2, then the range
+ * has not yet been measured, and is invalid.
+ */
+ bool IsRangeValid() const;
+
+ /**
+ * Turn Automatic mode on/off.
+ *
+ * When in Automatic mode, all sensors will fire in round robin, waiting a set
+ * time between each sensor.
+ *
+ * @param enabling Set to true if round robin scheduling should start for all
+ * the ultrasonic sensors. This scheduling method assures that
+ * the sensors are non-interfering because no two sensors fire
+ * at the same time. If another scheduling algorithm is
+ * prefered, it can be implemented by pinging the sensors
+ * manually and waiting for the results to come back.
+ */
+ static void SetAutomaticMode(bool enabling);
+
+ /**
+ * Get the range in inches from the ultrasonic sensor.
+ *
+ * @return Range in inches of the target returned from the ultrasonic sensor.
+ * If there is no valid value yet, i.e. at least one measurement
+ * hasn't completed, then return 0.
+ */
+ double GetRangeInches() const;
+
+ /**
+ * Get the range in millimeters from the ultrasonic sensor.
+ *
+ * @return Range in millimeters of the target returned by the ultrasonic
+ * sensor. If there is no valid value yet, i.e. at least one
+ * measurement hasn't completed, then return 0.
+ */
+ double GetRangeMM() const;
+
+ bool IsEnabled() const;
+
+ void SetEnabled(bool enable);
+
+ /**
+ * Set the current DistanceUnit that should be used for the PIDSource base
+ * object.
+ *
+ * @param units The DistanceUnit that should be used.
+ */
+ void SetDistanceUnits(DistanceUnit units);
+
+ /**
+ * Get the current DistanceUnit that is used for the PIDSource base object.
+ *
+ * @return The type of DistanceUnit that is being used.
+ */
+ DistanceUnit GetDistanceUnits() const;
+
+ /**
+ * Get the range in the current DistanceUnit for the PIDSource base object.
+ *
+ * @return The range in DistanceUnit
+ */
+ double PIDGet() override;
+
+ void SetPIDSourceType(PIDSourceType pidSource) override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ /**
+ * Initialize the Ultrasonic Sensor.
+ *
+ * This is the common code that initializes the ultrasonic sensor given that
+ * there are two digital I/O channels allocated. If the system was running in
+ * automatic mode (round robin) when the new sensor is added, it is stopped,
+ * the sensor is added, then automatic mode is restored.
+ */
+ void Initialize();
+
+ /**
+ * Background task that goes through the list of ultrasonic sensors and pings
+ * each one in turn. The counter is configured to read the timing of the
+ * returned echo pulse.
+ *
+ * DANGER WILL ROBINSON, DANGER WILL ROBINSON:
+ * This code runs as a task and assumes that none of the ultrasonic sensors
+ * will change while it's running. Make sure to disable automatic mode before
+ * touching the list.
+ */
+ static void UltrasonicChecker();
+
+ // Time (sec) for the ping trigger pulse.
+ static constexpr double kPingTime = 10 * 1e-6;
+
+ // Priority that the ultrasonic round robin task runs.
+ static constexpr int kPriority = 64;
+
+ // Max time (ms) between readings.
+ static constexpr double kMaxUltrasonicTime = 0.1;
+ static constexpr double kSpeedOfSoundInchesPerSec = 1130.0 * 12.0;
+
+ // Thread doing the round-robin automatic sensing
+ static std::thread m_thread;
+
+ // Ultrasonic sensors
+ static std::vector<Ultrasonic*> m_sensors;
+
+ // Automatic round-robin mode
+ static std::atomic<bool> m_automaticEnabled;
+
+ std::shared_ptr<DigitalOutput> m_pingChannel;
+ std::shared_ptr<DigitalInput> m_echoChannel;
+ bool m_enabled = false;
+ Counter m_counter;
+ DistanceUnit m_units;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Utility.h b/wpilibc/src/main/native/include/frc/Utility.h
new file mode 100644
index 0000000..9cb7abb
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Utility.h
@@ -0,0 +1,127 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+/**
+ * @file Contains global utility functions
+ */
+
+#include <stdint.h>
+
+#include <string>
+
+#include <wpi/StringRef.h>
+#include <wpi/Twine.h>
+#include <wpi/deprecated.h>
+
+#define wpi_assert(condition) \
+ wpi_assert_impl(condition, #condition, "", __FILE__, __LINE__, __FUNCTION__)
+#define wpi_assertWithMessage(condition, message) \
+ wpi_assert_impl(condition, #condition, message, __FILE__, __LINE__, \
+ __FUNCTION__)
+
+#define wpi_assertEqual(a, b) \
+ wpi_assertEqual_impl(a, b, #a, #b, "", __FILE__, __LINE__, __FUNCTION__)
+#define wpi_assertEqualWithMessage(a, b, message) \
+ wpi_assertEqual_impl(a, b, #a, #b, message, __FILE__, __LINE__, __FUNCTION__)
+
+#define wpi_assertNotEqual(a, b) \
+ wpi_assertNotEqual_impl(a, b, #a, #b, "", __FILE__, __LINE__, __FUNCTION__)
+#define wpi_assertNotEqualWithMessage(a, b, message) \
+ wpi_assertNotEqual_impl(a, b, #a, #b, message, __FILE__, __LINE__, \
+ __FUNCTION__)
+
+/**
+ * Assert implementation.
+ *
+ * This allows breakpoints to be set on an assert. The users don't call this,
+ * but instead use the wpi_assert macros in Utility.h.
+ */
+bool wpi_assert_impl(bool conditionValue, const wpi::Twine& conditionText,
+ const wpi::Twine& message, wpi::StringRef fileName,
+ int lineNumber, wpi::StringRef funcName);
+
+/**
+ * Assert equal implementation.
+ *
+ * This determines whether the two given integers are equal. If not, the value
+ * of each is printed along with an optional message string. The users don't
+ * call this, but instead use the wpi_assertEqual macros in Utility.h.
+ */
+bool wpi_assertEqual_impl(int valueA, int valueB,
+ const wpi::Twine& valueAString,
+ const wpi::Twine& valueBString,
+ const wpi::Twine& message, wpi::StringRef fileName,
+ int lineNumber, wpi::StringRef funcName);
+
+/**
+ * Assert not equal implementation.
+ *
+ * This determines whether the two given integers are equal. If so, the value of
+ * each is printed along with an optional message string. The users don't call
+ * this, but instead use the wpi_assertNotEqual macros in Utility.h.
+ */
+bool wpi_assertNotEqual_impl(int valueA, int valueB,
+ const wpi::Twine& valueAString,
+ const wpi::Twine& valueBString,
+ const wpi::Twine& message, wpi::StringRef fileName,
+ int lineNumber, wpi::StringRef funcName);
+
+namespace frc {
+
+/**
+ * Return the FPGA Version number.
+ *
+ * For now, expect this to be competition year.
+ *
+ * @return FPGA Version number.
+ * @deprecated Use RobotController static class method
+ */
+WPI_DEPRECATED("Use RobotController static class method")
+int GetFPGAVersion();
+
+/**
+ * Return the FPGA Revision number.
+ *
+ * The format of the revision is 3 numbers. The 12 most significant bits are the
+ * Major Revision. The next 8 bits are the Minor Revision. The 12 least
+ * significant bits are the Build Number.
+ *
+ * @return FPGA Revision number.
+ * @deprecated Use RobotController static class method
+ */
+WPI_DEPRECATED("Use RobotController static class method")
+int64_t GetFPGARevision();
+
+/**
+ * Read the microsecond-resolution timer on the FPGA.
+ *
+ * @return The current time in microseconds according to the FPGA (since FPGA
+ * reset).
+ * @deprecated Use RobotController static class method
+ */
+WPI_DEPRECATED("Use RobotController static class method")
+uint64_t GetFPGATime();
+
+/**
+ * Get the state of the "USER" button on the roboRIO.
+ *
+ * @return True if the button is currently pressed down
+ * @deprecated Use RobotController static class method
+ */
+WPI_DEPRECATED("Use RobotController static class method")
+bool GetUserButton();
+
+/**
+ * Get a stack trace, ignoring the first "offset" symbols.
+ *
+ * @param offset The number of symbols at the top of the stack to ignore
+ */
+std::string GetStackTrace(int offset);
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/Victor.h b/wpilibc/src/main/native/include/frc/Victor.h
new file mode 100644
index 0000000..5b6cba4
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Victor.h
@@ -0,0 +1,34 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PWMSpeedController.h"
+
+namespace frc {
+
+/**
+ * Vex Robotics Victor 888 Speed Controller.
+ *
+ * The Vex Robotics Victor 884 Speed Controller can also be used with this
+ * class but may need to be calibrated per the Victor 884 user manual.
+ */
+class Victor : public PWMSpeedController {
+ public:
+ /**
+ * Constructor for a Victor.
+ *
+ * @param channel The PWM channel number that the Victor is attached to. 0-9
+ * are on-board, 10-19 are on the MXP port
+ */
+ explicit Victor(int channel);
+
+ Victor(Victor&&) = default;
+ Victor& operator=(Victor&&) = default;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/VictorSP.h b/wpilibc/src/main/native/include/frc/VictorSP.h
new file mode 100644
index 0000000..b23fba1
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/VictorSP.h
@@ -0,0 +1,31 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PWMSpeedController.h"
+
+namespace frc {
+
+/**
+ * Vex Robotics Victor SP Speed Controller.
+ */
+class VictorSP : public PWMSpeedController {
+ public:
+ /**
+ * Constructor for a VictorSP.
+ *
+ * @param channel The PWM channel that the VictorSP is attached to. 0-9 are
+ * on-board, 10-19 are on the MXP port
+ */
+ explicit VictorSP(int channel);
+
+ VictorSP(VictorSP&&) = default;
+ VictorSP& operator=(VictorSP&&) = default;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/WPIErrors.h b/wpilibc/src/main/native/include/frc/WPIErrors.h
new file mode 100644
index 0000000..a7c4f16
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/WPIErrors.h
@@ -0,0 +1,101 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdint.h>
+
+#ifdef WPI_ERRORS_DEFINE_STRINGS
+#define S(label, offset, message) \
+ const char* wpi_error_s_##label = message; \
+ constexpr int wpi_error_value_##label = offset
+#else
+#define S(label, offset, message) \
+ extern const char* wpi_error_s_##label; \
+ constexpr int wpi_error_value_##label = offset
+#endif
+
+// Fatal errors
+S(ModuleIndexOutOfRange, -1,
+ "Allocating module that is out of range or not found");
+S(ChannelIndexOutOfRange, -1, "Allocating channel that is out of range");
+S(NotAllocated, -2, "Attempting to free unallocated resource");
+S(ResourceAlreadyAllocated, -3, "Attempted to reuse an allocated resource");
+S(NoAvailableResources, -4, "No available resources to allocate");
+S(NullParameter, -5, "A pointer parameter to a method is nullptr");
+S(Timeout, -6, "A timeout has been exceeded");
+S(CompassManufacturerError, -7, "Compass manufacturer doesn't match HiTechnic");
+S(CompassTypeError, -8,
+ "Compass type doesn't match expected type for HiTechnic compass");
+S(IncompatibleMode, -9, "The object is in an incompatible mode");
+S(AnalogTriggerLimitOrderError, -10,
+ "AnalogTrigger limits error. Lower limit > Upper Limit");
+S(AnalogTriggerPulseOutputError, -11,
+ "Attempted to read AnalogTrigger pulse output.");
+S(TaskError, -12, "Task can't be started");
+S(TaskIDError, -13, "Task error: Invalid ID.");
+S(TaskDeletedError, -14, "Task error: Task already deleted.");
+S(TaskOptionsError, -15, "Task error: Invalid options.");
+S(TaskMemoryError, -16, "Task can't be started due to insufficient memory.");
+S(TaskPriorityError, -17, "Task error: Invalid priority [1-255].");
+S(DriveUninitialized, -18, "RobotDrive not initialized for the C interface");
+S(CompressorNonMatching, -19,
+ "Compressor slot/channel doesn't match previous instance");
+S(CompressorAlreadyDefined, -20, "Creating a second compressor instance");
+S(CompressorUndefined, -21,
+ "Using compressor functions without defining compressor");
+S(InconsistentArrayValueAdded, -22,
+ "When packing data into an array to the dashboard, not all values added were "
+ "of the same type.");
+S(MismatchedComplexTypeClose, -23,
+ "When packing data to the dashboard, a Close for a complex type was called "
+ "without a matching Open.");
+S(DashboardDataOverflow, -24,
+ "When packing data to the dashboard, too much data was packed and the buffer "
+ "overflowed.");
+S(DashboardDataCollision, -25,
+ "The same buffer was used for packing data and for printing.");
+S(EnhancedIOMissing, -26, "IO is not attached or Enhanced IO is not enabled.");
+S(LineNotOutput, -27,
+ "Cannot SetDigitalOutput for a line not configured for output.");
+S(ParameterOutOfRange, -28, "A parameter is out of range.");
+S(SPIClockRateTooLow, -29, "SPI clock rate was below the minimum supported");
+S(JaguarVersionError, -30, "Jaguar firmware version error");
+S(JaguarMessageNotFound, -31, "Jaguar message not found");
+S(NetworkTablesReadError, -40, "Error reading NetworkTables socket");
+S(NetworkTablesBufferFull, -41, "Buffer full writing to NetworkTables socket");
+S(NetworkTablesWrongType, -42,
+ "The wrong type was read from the NetworkTables entry");
+S(NetworkTablesCorrupt, -43, "NetworkTables data stream is corrupt");
+S(SmartDashboardMissingKey, -43, "SmartDashboard data does not exist");
+S(CommandIllegalUse, -50, "Illegal use of Command");
+S(UnsupportedInSimulation, -80, "Unsupported in simulation");
+S(CameraServerError, -90, "CameraServer error");
+S(InvalidParameter, -100, "Invalid parameter value");
+
+// Warnings
+S(SampleRateTooHigh, 1, "Analog module sample rate is too high");
+S(VoltageOutOfRange, 2,
+ "Voltage to convert to raw value is out of range [-10; 10]");
+S(CompressorTaskError, 3, "Compressor task won't start");
+S(LoopTimingError, 4, "Digital module loop timing is not the expected value");
+S(NonBinaryDigitalValue, 5, "Digital output value is not 0 or 1");
+S(IncorrectBatteryChannel, 6,
+ "Battery measurement channel is not correct value");
+S(BadJoystickIndex, 7, "Joystick index is out of range, should be 0-3");
+S(BadJoystickAxis, 8, "Joystick axis or POV is out of range");
+S(InvalidMotorIndex, 9, "Motor index is out of range, should be 0-3");
+S(DriverStationTaskError, 10, "Driver Station task won't start");
+S(EnhancedIOPWMPeriodOutOfRange, 11,
+ "Driver Station Enhanced IO PWM Output period out of range.");
+S(SPIWriteNoMOSI, 12, "Cannot write to SPI port with no MOSI output");
+S(SPIReadNoMISO, 13, "Cannot read from SPI port with no MISO input");
+S(SPIReadNoData, 14, "No data available to read from SPI");
+S(IncompatibleState, 15,
+ "Incompatible State: The operation cannot be completed");
+
+#undef S
diff --git a/wpilibc/src/main/native/include/frc/WPILib.h b/wpilibc/src/main/native/include/frc/WPILib.h
new file mode 100644
index 0000000..27c7b69
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/WPILib.h
@@ -0,0 +1,100 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <cameraserver/CameraServer.h>
+#include <vision/VisionRunner.h>
+
+#include "frc/ADXL345_I2C.h"
+#include "frc/ADXL345_SPI.h"
+#include "frc/ADXL362.h"
+#include "frc/ADXRS450_Gyro.h"
+#include "frc/AnalogAccelerometer.h"
+#include "frc/AnalogGyro.h"
+#include "frc/AnalogInput.h"
+#include "frc/AnalogOutput.h"
+#include "frc/AnalogPotentiometer.h"
+#include "frc/AnalogTrigger.h"
+#include "frc/AnalogTriggerOutput.h"
+#include "frc/BuiltInAccelerometer.h"
+#include "frc/Compressor.h"
+#include "frc/ControllerPower.h"
+#include "frc/Counter.h"
+#include "frc/DMC60.h"
+#include "frc/DigitalInput.h"
+#include "frc/DigitalOutput.h"
+#include "frc/DigitalSource.h"
+#include "frc/DoubleSolenoid.h"
+#include "frc/DriverStation.h"
+#include "frc/Encoder.h"
+#include "frc/ErrorBase.h"
+#include "frc/GearTooth.h"
+#include "frc/GenericHID.h"
+#include "frc/I2C.h"
+#include "frc/InterruptableSensorBase.h"
+#include "frc/IterativeRobot.h"
+#include "frc/Jaguar.h"
+#include "frc/Joystick.h"
+#include "frc/NidecBrushless.h"
+#include "frc/Notifier.h"
+#include "frc/PIDController.h"
+#include "frc/PIDOutput.h"
+#include "frc/PIDSource.h"
+#include "frc/PWM.h"
+#include "frc/PWMSpeedController.h"
+#include "frc/PWMTalonSRX.h"
+#include "frc/PWMVictorSPX.h"
+#include "frc/PowerDistributionPanel.h"
+#include "frc/Preferences.h"
+#include "frc/Relay.h"
+#include "frc/RobotBase.h"
+#include "frc/RobotController.h"
+#include "frc/RobotDrive.h"
+#include "frc/SD540.h"
+#include "frc/SPI.h"
+#include "frc/SampleRobot.h"
+#include "frc/SensorUtil.h"
+#include "frc/SerialPort.h"
+#include "frc/Servo.h"
+#include "frc/Solenoid.h"
+#include "frc/Spark.h"
+#include "frc/SpeedController.h"
+#include "frc/SpeedControllerGroup.h"
+#include "frc/Talon.h"
+#include "frc/Threads.h"
+#include "frc/TimedRobot.h"
+#include "frc/Timer.h"
+#include "frc/Ultrasonic.h"
+#include "frc/Utility.h"
+#include "frc/Victor.h"
+#include "frc/VictorSP.h"
+#include "frc/WPIErrors.h"
+#include "frc/XboxController.h"
+#include "frc/buttons/InternalButton.h"
+#include "frc/buttons/JoystickButton.h"
+#include "frc/buttons/NetworkButton.h"
+#include "frc/commands/Command.h"
+#include "frc/commands/CommandGroup.h"
+#include "frc/commands/PIDCommand.h"
+#include "frc/commands/PIDSubsystem.h"
+#include "frc/commands/PrintCommand.h"
+#include "frc/commands/Scheduler.h"
+#include "frc/commands/StartCommand.h"
+#include "frc/commands/Subsystem.h"
+#include "frc/commands/WaitCommand.h"
+#include "frc/commands/WaitForChildren.h"
+#include "frc/commands/WaitUntilCommand.h"
+#include "frc/drive/DifferentialDrive.h"
+#include "frc/drive/KilloughDrive.h"
+#include "frc/drive/MecanumDrive.h"
+#include "frc/filters/LinearDigitalFilter.h"
+#include "frc/interfaces/Accelerometer.h"
+#include "frc/interfaces/Gyro.h"
+#include "frc/interfaces/Potentiometer.h"
+#include "frc/smartdashboard/SendableChooser.h"
+#include "frc/smartdashboard/SmartDashboard.h"
diff --git a/wpilibc/src/main/native/include/frc/Watchdog.h b/wpilibc/src/main/native/include/frc/Watchdog.h
new file mode 100644
index 0000000..e15da1f
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/Watchdog.h
@@ -0,0 +1,141 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <chrono>
+#include <functional>
+#include <utility>
+
+#include <hal/cpp/fpga_clock.h>
+#include <wpi/SafeThread.h>
+#include <wpi/StringMap.h>
+#include <wpi/StringRef.h>
+
+namespace frc {
+
+/**
+ * A class that's a wrapper around a watchdog timer.
+ *
+ * When the timer expires, a message is printed to the console and an optional
+ * user-provided callback is invoked.
+ *
+ * The watchdog is initialized disabled, so the user needs to call Enable()
+ * before use.
+ */
+class Watchdog {
+ public:
+ /**
+ * Watchdog constructor.
+ *
+ * @param timeout The watchdog's timeout in seconds with microsecond
+ * resolution.
+ * @param callback This function is called when the timeout expires.
+ */
+ Watchdog(double timeout, std::function<void()> callback);
+
+ template <typename Callable, typename Arg, typename... Args>
+ Watchdog(double timeout, Callable&& f, Arg&& arg, Args&&... args)
+ : Watchdog(timeout,
+ std::bind(std::forward<Callable>(f), std::forward<Arg>(arg),
+ std::forward<Args>(args)...)) {}
+
+ ~Watchdog();
+
+ Watchdog(Watchdog&&) = default;
+ Watchdog& operator=(Watchdog&&) = default;
+
+ /**
+ * Returns the time in seconds since the watchdog was last fed.
+ */
+ double GetTime() const;
+
+ /**
+ * Sets the watchdog's timeout.
+ *
+ * @param timeout The watchdog's timeout in seconds with microsecond
+ * resolution.
+ */
+ void SetTimeout(double timeout);
+
+ /**
+ * Returns the watchdog's timeout in seconds.
+ */
+ double GetTimeout() const;
+
+ /**
+ * Returns true if the watchdog timer has expired.
+ */
+ bool IsExpired() const;
+
+ /**
+ * Adds time since last epoch to the list printed by PrintEpochs().
+ *
+ * Epochs are a way to partition the time elapsed so that when overruns occur,
+ * one can determine which parts of an operation consumed the most time.
+ *
+ * @param epochName The name to associate with the epoch.
+ */
+ void AddEpoch(wpi::StringRef epochName);
+
+ /**
+ * Prints list of epochs added so far and their times.
+ */
+ void PrintEpochs();
+
+ /**
+ * Resets the watchdog timer.
+ *
+ * This also enables the timer if it was previously disabled.
+ */
+ void Reset();
+
+ /**
+ * Enables the watchdog timer.
+ */
+ void Enable();
+
+ /**
+ * Disables the watchdog timer.
+ */
+ void Disable();
+
+ /**
+ * Enable or disable suppression of the generic timeout message.
+ *
+ * This may be desirable if the user-provided callback already prints a more
+ * specific message.
+ *
+ * @param suppress Whether to suppress generic timeout message.
+ */
+ void SuppressTimeoutMessage(bool suppress);
+
+ private:
+ // Used for timeout print rate-limiting
+ static constexpr std::chrono::milliseconds kMinPrintPeriod{1000};
+
+ hal::fpga_clock::time_point m_startTime;
+ std::chrono::microseconds m_timeout;
+ hal::fpga_clock::time_point m_expirationTime;
+ std::function<void()> m_callback;
+ hal::fpga_clock::time_point m_lastTimeoutPrintTime = hal::fpga_clock::epoch();
+ hal::fpga_clock::time_point m_lastEpochsPrintTime = hal::fpga_clock::epoch();
+
+ wpi::StringMap<std::chrono::microseconds> m_epochs;
+ bool m_isExpired = false;
+
+ bool m_suppressTimeoutMessage = false;
+
+ class Thread;
+ wpi::SafeThreadOwner<Thread>* m_owner;
+
+ bool operator>(const Watchdog& rhs);
+
+ static wpi::SafeThreadOwner<Thread>& GetThreadOwner();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/XboxController.h b/wpilibc/src/main/native/include/frc/XboxController.h
new file mode 100644
index 0000000..8aa2d5b
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/XboxController.h
@@ -0,0 +1,250 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/GenericHID.h"
+
+namespace frc {
+
+/**
+ * Handle input from Xbox 360 or Xbox One controllers connected to the Driver
+ * Station.
+ *
+ * This class handles Xbox input that comes from the Driver Station. Each time a
+ * value is requested the most recent value is returned. There is a single class
+ * instance for each controller and the mapping of ports to hardware buttons
+ * depends on the code in the Driver Station.
+ */
+class XboxController : public GenericHID {
+ public:
+ /**
+ * Construct an instance of an Xbox controller.
+ *
+ * The controller index is the USB port on the Driver Station.
+ *
+ * @param port The port on the Driver Station that the controller is plugged
+ * into (0-5).
+ */
+ explicit XboxController(int port);
+
+ virtual ~XboxController() = default;
+
+ XboxController(XboxController&&) = default;
+ XboxController& operator=(XboxController&&) = default;
+
+ /**
+ * Get the X axis value of the controller.
+ *
+ * @param hand Side of controller whose value should be returned.
+ */
+ double GetX(JoystickHand hand) const override;
+
+ /**
+ * Get the Y axis value of the controller.
+ *
+ * @param hand Side of controller whose value should be returned.
+ */
+ double GetY(JoystickHand hand) const override;
+
+ /**
+ * Get the trigger axis value of the controller.
+ *
+ * @param hand Side of controller whose value should be returned.
+ */
+ double GetTriggerAxis(JoystickHand hand) const;
+
+ /**
+ * Read the value of the bumper button on the controller.
+ *
+ * @param hand Side of controller whose value should be returned.
+ */
+ bool GetBumper(JoystickHand hand) const;
+
+ /**
+ * Whether the bumper was pressed since the last check.
+ *
+ * @param hand Side of controller whose value should be returned.
+ * @return Whether the button was pressed since the last check.
+ */
+ bool GetBumperPressed(JoystickHand hand);
+
+ /**
+ * Whether the bumper was released since the last check.
+ *
+ * @param hand Side of controller whose value should be returned.
+ * @return Whether the button was released since the last check.
+ */
+ bool GetBumperReleased(JoystickHand hand);
+
+ /**
+ * Read the value of the stick button on the controller.
+ *
+ * @param hand Side of controller whose value should be returned.
+ * @return The state of the button.
+ */
+ bool GetStickButton(JoystickHand hand) const;
+
+ /**
+ * Whether the stick button was pressed since the last check.
+ *
+ * @param hand Side of controller whose value should be returned.
+ * @return Whether the button was pressed since the last check.
+ */
+ bool GetStickButtonPressed(JoystickHand hand);
+
+ /**
+ * Whether the stick button was released since the last check.
+ *
+ * @param hand Side of controller whose value should be returned.
+ * @return Whether the button was released since the last check.
+ */
+ bool GetStickButtonReleased(JoystickHand hand);
+
+ /**
+ * Read the value of the A button on the controller.
+ *
+ * @return The state of the button.
+ */
+ bool GetAButton() const;
+
+ /**
+ * Whether the A button was pressed since the last check.
+ *
+ * @return Whether the button was pressed since the last check.
+ */
+ bool GetAButtonPressed();
+
+ /**
+ * Whether the A button was released since the last check.
+ *
+ * @return Whether the button was released since the last check.
+ */
+ bool GetAButtonReleased();
+
+ /**
+ * Read the value of the B button on the controller.
+ *
+ * @return The state of the button.
+ */
+ bool GetBButton() const;
+
+ /**
+ * Whether the B button was pressed since the last check.
+ *
+ * @return Whether the button was pressed since the last check.
+ */
+ bool GetBButtonPressed();
+
+ /**
+ * Whether the B button was released since the last check.
+ *
+ * @return Whether the button was released since the last check.
+ */
+ bool GetBButtonReleased();
+
+ /**
+ * Read the value of the X button on the controller.
+ *
+ * @return The state of the button.
+ */
+ bool GetXButton() const;
+
+ /**
+ * Whether the X button was pressed since the last check.
+ *
+ * @return Whether the button was pressed since the last check.
+ */
+ bool GetXButtonPressed();
+
+ /**
+ * Whether the X button was released since the last check.
+ *
+ * @return Whether the button was released since the last check.
+ */
+ bool GetXButtonReleased();
+
+ /**
+ * Read the value of the Y button on the controller.
+ *
+ * @return The state of the button.
+ */
+ bool GetYButton() const;
+
+ /**
+ * Whether the Y button was pressed since the last check.
+ *
+ * @return Whether the button was pressed since the last check.
+ */
+ bool GetYButtonPressed();
+
+ /**
+ * Whether the Y button was released since the last check.
+ *
+ * @return Whether the button was released since the last check.
+ */
+ bool GetYButtonReleased();
+
+ /**
+ * Whether the Y button was released since the last check.
+ *
+ * @return Whether the button was released since the last check.
+ */
+ bool GetBackButton() const;
+
+ /**
+ * Whether the back button was pressed since the last check.
+ *
+ * @return Whether the button was pressed since the last check.
+ */
+ bool GetBackButtonPressed();
+
+ /**
+ * Whether the back button was released since the last check.
+ *
+ * @return Whether the button was released since the last check.
+ */
+ bool GetBackButtonReleased();
+
+ /**
+ * Read the value of the start button on the controller.
+ *
+ * @param hand Side of controller whose value should be returned.
+ * @return The state of the button.
+ */
+ bool GetStartButton() const;
+
+ /**
+ * Whether the start button was pressed since the last check.
+ *
+ * @return Whether the button was pressed since the last check.
+ */
+ bool GetStartButtonPressed();
+
+ /**
+ * Whether the start button was released since the last check.
+ *
+ * @return Whether the button was released since the last check.
+ */
+ bool GetStartButtonReleased();
+
+ private:
+ enum class Button {
+ kBumperLeft = 5,
+ kBumperRight = 6,
+ kStickLeft = 9,
+ kStickRight = 10,
+ kA = 1,
+ kB = 2,
+ kX = 3,
+ kY = 4,
+ kBack = 7,
+ kStart = 8
+ };
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/buttons/Button.h b/wpilibc/src/main/native/include/frc/buttons/Button.h
new file mode 100644
index 0000000..71641e9
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/buttons/Button.h
@@ -0,0 +1,73 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/buttons/Trigger.h"
+#include "frc/commands/Command.h"
+
+namespace frc {
+
+/**
+ * This class provides an easy way to link commands to OI inputs.
+ *
+ * It is very easy to link a button to a command. For instance, you could link
+ * the trigger button of a joystick to a "score" command.
+ *
+ * This class represents a subclass of Trigger that is specifically aimed at
+ * buttons on an operator interface as a common use case of the more generalized
+ * Trigger objects. This is a simple wrapper around Trigger with the method
+ * names renamed to fit the Button object use.
+ */
+class Button : public Trigger {
+ public:
+ Button() = default;
+ Button(Button&&) = default;
+ Button& operator=(Button&&) = default;
+
+ /**
+ * Specifies the command to run when a button is first pressed.
+ *
+ * @param command The pointer to the command to run
+ */
+ virtual void WhenPressed(Command* command);
+
+ /**
+ * Specifies the command to be scheduled while the button is pressed.
+ *
+ * The command will be scheduled repeatedly while the button is pressed and
+ * will be canceled when the button is released.
+ *
+ * @param command The pointer to the command to run
+ */
+ virtual void WhileHeld(Command* command);
+
+ /**
+ * Specifies the command to run when the button is released.
+ *
+ * The command will be scheduled a single time.
+ *
+ * @param command The pointer to the command to run
+ */
+ virtual void WhenReleased(Command* command);
+
+ /**
+ * Cancels the specificed command when the button is pressed.
+ *
+ * @param command The command to be canceled
+ */
+ virtual void CancelWhenPressed(Command* command);
+
+ /**
+ * Toggle the specified command when the button is pressed.
+ *
+ * @param command The command to be toggled
+ */
+ virtual void ToggleWhenPressed(Command* command);
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/buttons/ButtonScheduler.h b/wpilibc/src/main/native/include/frc/buttons/ButtonScheduler.h
new file mode 100644
index 0000000..ec2e35b
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/buttons/ButtonScheduler.h
@@ -0,0 +1,32 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+class Trigger;
+class Command;
+
+class ButtonScheduler {
+ public:
+ ButtonScheduler(bool last, Trigger* button, Command* orders);
+ virtual ~ButtonScheduler() = default;
+
+ ButtonScheduler(ButtonScheduler&&) = default;
+ ButtonScheduler& operator=(ButtonScheduler&&) = default;
+
+ virtual void Execute() = 0;
+ void Start();
+
+ protected:
+ bool m_pressedLast;
+ Trigger* m_button;
+ Command* m_command;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/buttons/CancelButtonScheduler.h b/wpilibc/src/main/native/include/frc/buttons/CancelButtonScheduler.h
new file mode 100644
index 0000000..69b8a11
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/buttons/CancelButtonScheduler.h
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/buttons/ButtonScheduler.h"
+
+namespace frc {
+
+class Trigger;
+class Command;
+
+class CancelButtonScheduler : public ButtonScheduler {
+ public:
+ CancelButtonScheduler(bool last, Trigger* button, Command* orders);
+ virtual ~CancelButtonScheduler() = default;
+
+ CancelButtonScheduler(CancelButtonScheduler&&) = default;
+ CancelButtonScheduler& operator=(CancelButtonScheduler&&) = default;
+
+ virtual void Execute();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/buttons/HeldButtonScheduler.h b/wpilibc/src/main/native/include/frc/buttons/HeldButtonScheduler.h
new file mode 100644
index 0000000..ad4a160
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/buttons/HeldButtonScheduler.h
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/buttons/ButtonScheduler.h"
+
+namespace frc {
+
+class Trigger;
+class Command;
+
+class HeldButtonScheduler : public ButtonScheduler {
+ public:
+ HeldButtonScheduler(bool last, Trigger* button, Command* orders);
+ virtual ~HeldButtonScheduler() = default;
+
+ HeldButtonScheduler(HeldButtonScheduler&&) = default;
+ HeldButtonScheduler& operator=(HeldButtonScheduler&&) = default;
+
+ virtual void Execute();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/buttons/InternalButton.h b/wpilibc/src/main/native/include/frc/buttons/InternalButton.h
new file mode 100644
index 0000000..430a21e
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/buttons/InternalButton.h
@@ -0,0 +1,33 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/buttons/Button.h"
+
+namespace frc {
+
+class InternalButton : public Button {
+ public:
+ InternalButton() = default;
+ explicit InternalButton(bool inverted);
+ virtual ~InternalButton() = default;
+
+ InternalButton(InternalButton&&) = default;
+ InternalButton& operator=(InternalButton&&) = default;
+
+ void SetInverted(bool inverted);
+ void SetPressed(bool pressed);
+
+ virtual bool Get();
+
+ private:
+ bool m_pressed = false;
+ bool m_inverted = false;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/buttons/JoystickButton.h b/wpilibc/src/main/native/include/frc/buttons/JoystickButton.h
new file mode 100644
index 0000000..1b4264f
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/buttons/JoystickButton.h
@@ -0,0 +1,30 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/GenericHID.h"
+#include "frc/buttons/Button.h"
+
+namespace frc {
+
+class JoystickButton : public Button {
+ public:
+ JoystickButton(GenericHID* joystick, int buttonNumber);
+ virtual ~JoystickButton() = default;
+
+ JoystickButton(JoystickButton&&) = default;
+ JoystickButton& operator=(JoystickButton&&) = default;
+
+ virtual bool Get();
+
+ private:
+ GenericHID* m_joystick;
+ int m_buttonNumber;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/buttons/NetworkButton.h b/wpilibc/src/main/native/include/frc/buttons/NetworkButton.h
new file mode 100644
index 0000000..fef8065
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/buttons/NetworkButton.h
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <networktables/NetworkTable.h>
+#include <networktables/NetworkTableEntry.h>
+#include <wpi/Twine.h>
+
+#include "frc/buttons/Button.h"
+
+namespace frc {
+
+class NetworkButton : public Button {
+ public:
+ NetworkButton(const wpi::Twine& tableName, const wpi::Twine& field);
+ NetworkButton(std::shared_ptr<nt::NetworkTable> table,
+ const wpi::Twine& field);
+ virtual ~NetworkButton() = default;
+
+ NetworkButton(NetworkButton&&) = default;
+ NetworkButton& operator=(NetworkButton&&) = default;
+
+ virtual bool Get();
+
+ private:
+ nt::NetworkTableEntry m_entry;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/buttons/POVButton.h b/wpilibc/src/main/native/include/frc/buttons/POVButton.h
new file mode 100644
index 0000000..15c4bf8
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/buttons/POVButton.h
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/GenericHID.h"
+#include "frc/buttons/Button.h"
+
+namespace frc {
+class POVButton : public Button {
+ public:
+ /**
+ * Creates a POV button for triggering commands.
+ *
+ * @param joystick The GenericHID object that has the POV
+ * @param angle The desired angle in degrees (e.g. 90, 270)
+ * @param povNumber The POV number (@see GenericHID#GetPOV)
+ */
+ POVButton(GenericHID& joystick, int angle, int povNumber = 0);
+ virtual ~POVButton() = default;
+
+ POVButton(POVButton&&) = default;
+ POVButton& operator=(POVButton&&) = default;
+
+ bool Get() override;
+
+ private:
+ GenericHID* m_joystick;
+ int m_angle;
+ int m_povNumber;
+};
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/buttons/PressedButtonScheduler.h b/wpilibc/src/main/native/include/frc/buttons/PressedButtonScheduler.h
new file mode 100644
index 0000000..0c1fb03
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/buttons/PressedButtonScheduler.h
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/buttons/ButtonScheduler.h"
+
+namespace frc {
+
+class Trigger;
+class Command;
+
+class PressedButtonScheduler : public ButtonScheduler {
+ public:
+ PressedButtonScheduler(bool last, Trigger* button, Command* orders);
+ virtual ~PressedButtonScheduler() = default;
+
+ PressedButtonScheduler(PressedButtonScheduler&&) = default;
+ PressedButtonScheduler& operator=(PressedButtonScheduler&&) = default;
+
+ virtual void Execute();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/buttons/ReleasedButtonScheduler.h b/wpilibc/src/main/native/include/frc/buttons/ReleasedButtonScheduler.h
new file mode 100644
index 0000000..899a483
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/buttons/ReleasedButtonScheduler.h
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/buttons/ButtonScheduler.h"
+
+namespace frc {
+
+class Trigger;
+class Command;
+
+class ReleasedButtonScheduler : public ButtonScheduler {
+ public:
+ ReleasedButtonScheduler(bool last, Trigger* button, Command* orders);
+ virtual ~ReleasedButtonScheduler() = default;
+
+ ReleasedButtonScheduler(ReleasedButtonScheduler&&) = default;
+ ReleasedButtonScheduler& operator=(ReleasedButtonScheduler&&) = default;
+
+ virtual void Execute();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/buttons/ToggleButtonScheduler.h b/wpilibc/src/main/native/include/frc/buttons/ToggleButtonScheduler.h
new file mode 100644
index 0000000..aeb93b3
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/buttons/ToggleButtonScheduler.h
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/buttons/ButtonScheduler.h"
+
+namespace frc {
+
+class Trigger;
+class Command;
+
+class ToggleButtonScheduler : public ButtonScheduler {
+ public:
+ ToggleButtonScheduler(bool last, Trigger* button, Command* orders);
+ virtual ~ToggleButtonScheduler() = default;
+
+ ToggleButtonScheduler(ToggleButtonScheduler&&) = default;
+ ToggleButtonScheduler& operator=(ToggleButtonScheduler&&) = default;
+
+ virtual void Execute();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/buttons/Trigger.h b/wpilibc/src/main/native/include/frc/buttons/Trigger.h
new file mode 100644
index 0000000..8f8c477
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/buttons/Trigger.h
@@ -0,0 +1,53 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <atomic>
+
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class Command;
+
+/**
+ * This class provides an easy way to link commands to inputs.
+ *
+ * It is very easy to link a polled input to a command. For instance, you could
+ * link the trigger button of a joystick to a "score" command or an encoder
+ * reaching a particular value.
+ *
+ * It is encouraged that teams write a subclass of Trigger if they want to have
+ * something unusual (for instance, if they want to react to the user holding
+ * a button while the robot is reading a certain sensor input). For this, they
+ * only have to write the {@link Trigger#Get()} method to get the full
+ * functionality of the Trigger class.
+ */
+class Trigger : public SendableBase {
+ public:
+ Trigger() = default;
+ ~Trigger() override = default;
+
+ Trigger(Trigger&&) = default;
+ Trigger& operator=(Trigger&&) = default;
+
+ bool Grab();
+ virtual bool Get() = 0;
+ void WhenActive(Command* command);
+ void WhileActive(Command* command);
+ void WhenInactive(Command* command);
+ void CancelWhenActive(Command* command);
+ void ToggleWhenActive(Command* command);
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ std::atomic_bool m_sendablePressed{false};
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/circular_buffer.h b/wpilibc/src/main/native/include/frc/circular_buffer.h
new file mode 100644
index 0000000..b5ebd16
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/circular_buffer.h
@@ -0,0 +1,62 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <cstddef>
+#include <vector>
+
+namespace frc {
+
+/**
+ * This is a simple circular buffer so we don't need to "bucket brigade" copy
+ * old values.
+ */
+template <class T>
+class circular_buffer {
+ public:
+ explicit circular_buffer(size_t size);
+
+ using value_type = T;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using pointer = value_type*;
+ using size_type = size_t;
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
+
+ size_type size() const;
+ T& front();
+ const T& front() const;
+ T& back();
+ const T& back() const;
+ void push_front(T value);
+ void push_back(T value);
+ T pop_front();
+ T pop_back();
+ void resize(size_t size);
+ void reset();
+
+ T& operator[](size_t index);
+ const T& operator[](size_t index) const;
+
+ private:
+ std::vector<T> m_data;
+
+ // Index of element at front of buffer
+ size_t m_front = 0;
+
+ // Number of elements used in buffer
+ size_t m_length = 0;
+
+ size_t ModuloInc(size_t index);
+ size_t ModuloDec(size_t index);
+};
+
+} // namespace frc
+
+#include "frc/circular_buffer.inc"
diff --git a/wpilibc/src/main/native/include/frc/circular_buffer.inc b/wpilibc/src/main/native/include/frc/circular_buffer.inc
new file mode 100644
index 0000000..4af5040
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/circular_buffer.inc
@@ -0,0 +1,239 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <algorithm>
+
+namespace frc {
+
+template <class T>
+circular_buffer<T>::circular_buffer(size_t size) : m_data(size, 0) {}
+
+/**
+ * Returns number of elements in buffer
+ */
+template <class T>
+typename circular_buffer<T>::size_type circular_buffer<T>::size() const {
+ return m_length;
+}
+
+/**
+ * Returns value at front of buffer
+ */
+template <class T>
+T& circular_buffer<T>::front() {
+ return (*this)[0];
+}
+
+/**
+ * Returns value at front of buffer
+ */
+template <class T>
+const T& circular_buffer<T>::front() const {
+ return (*this)[0];
+}
+
+/**
+ * Returns value at back of buffer
+ */
+template <class T>
+T& circular_buffer<T>::back() {
+ // If there are no elements in the buffer, do nothing
+ if (m_length == 0) {
+ return 0;
+ }
+
+ return m_data[(m_front + m_length - 1) % m_data.size()];
+}
+
+/**
+ * Returns value at back of buffer
+ */
+template <class T>
+const T& circular_buffer<T>::back() const {
+ // If there are no elements in the buffer, do nothing
+ if (m_length == 0) {
+ return 0;
+ }
+
+ return m_data[(m_front + m_length - 1) % m_data.size()];
+}
+
+/**
+ * Push new value onto front of the buffer. The value at the back is overwritten
+ * if the buffer is full.
+ */
+template <class T>
+void circular_buffer<T>::push_front(T value) {
+ if (m_data.size() == 0) {
+ return;
+ }
+
+ m_front = ModuloDec(m_front);
+
+ m_data[m_front] = value;
+
+ if (m_length < m_data.size()) {
+ m_length++;
+ }
+}
+
+/**
+ * Push new value onto back of the buffer. The value at the front is overwritten
+ * if the buffer is full.
+ */
+template <class T>
+void circular_buffer<T>::push_back(T value) {
+ if (m_data.size() == 0) {
+ return;
+ }
+
+ m_data[(m_front + m_length) % m_data.size()] = value;
+
+ if (m_length < m_data.size()) {
+ m_length++;
+ } else {
+ // Increment front if buffer is full to maintain size
+ m_front = ModuloInc(m_front);
+ }
+}
+
+/**
+ * Pop value at front of buffer.
+ */
+template <class T>
+T circular_buffer<T>::pop_front() {
+ // If there are no elements in the buffer, do nothing
+ if (m_length == 0) {
+ return 0;
+ }
+
+ T& temp = m_data[m_front];
+ m_front = ModuloInc(m_front);
+ m_length--;
+ return temp;
+}
+
+/**
+ * Pop value at back of buffer.
+ */
+template <class T>
+T circular_buffer<T>::pop_back() {
+ // If there are no elements in the buffer, do nothing
+ if (m_length == 0) {
+ return 0;
+ }
+
+ m_length--;
+ return m_data[(m_front + m_length) % m_data.size()];
+}
+
+/**
+ * Resizes internal buffer to given size.
+ */
+template <class T>
+void circular_buffer<T>::resize(size_t size) {
+ if (size > m_data.size()) {
+ // Find end of buffer
+ size_t insertLocation = (m_front + m_length) % m_data.size();
+
+ // If insertion location precedes front of buffer, push front index back
+ if (insertLocation <= m_front) {
+ m_front += size - m_data.size();
+ }
+
+ // Add elements to end of buffer
+ m_data.insert(m_data.begin() + insertLocation, size - m_data.size(), 0);
+ } else if (size < m_data.size()) {
+ /* 1) Shift element block start at "front" left as many blocks as were
+ * removed up to but not exceeding buffer[0]
+ * 2) Shrink buffer, which will remove even more elements automatically if
+ * necessary
+ */
+ size_t elemsToRemove = m_data.size() - size;
+ auto frontIter = m_data.begin() + m_front;
+ if (m_front < elemsToRemove) {
+ /* Remove elements from end of buffer before shifting start of element
+ * block. Doing so saves a few copies.
+ */
+ m_data.erase(frontIter + size, m_data.end());
+
+ // Shift start of element block to left
+ m_data.erase(m_data.begin(), frontIter);
+
+ // Update metadata
+ m_front = 0;
+ } else {
+ // Shift start of element block to left
+ m_data.erase(frontIter - elemsToRemove, frontIter);
+
+ // Update metadata
+ m_front -= elemsToRemove;
+ }
+
+ /* Length only changes during a shrink if all unused spaces have been
+ * removed. Length decreases as used spaces are removed to meet the
+ * required size.
+ */
+ if (m_length > size) {
+ m_length = size;
+ }
+ }
+}
+
+/**
+ * Sets internal buffer contents to zero.
+ */
+template <class T>
+void circular_buffer<T>::reset() {
+ std::fill(m_data.begin(), m_data.end(), 0);
+ m_front = 0;
+ m_length = 0;
+}
+
+/**
+ * @return Element at index starting from front of buffer.
+ */
+template <class T>
+T& circular_buffer<T>::operator[](size_t index) {
+ return m_data[(m_front + index) % m_data.size()];
+}
+
+/**
+ * @return Element at index starting from front of buffer.
+ */
+template <class T>
+const T& circular_buffer<T>::operator[](size_t index) const {
+ return m_data[(m_front + index) % m_data.size()];
+}
+
+/**
+ * Increment an index modulo the length of the buffer.
+ *
+ * @return The result of the modulo operation.
+ */
+template <class T>
+size_t circular_buffer<T>::ModuloInc(size_t index) {
+ return (index + 1) % m_data.size();
+}
+
+/**
+ * Decrement an index modulo the length of the buffer.
+ *
+ * @return The result of the modulo operation.
+ */
+template <class T>
+size_t circular_buffer<T>::ModuloDec(size_t index) {
+ if (index == 0) {
+ return m_data.size() - 1;
+ } else {
+ return index - 1;
+ }
+}
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/Command.h b/wpilibc/src/main/native/include/frc/commands/Command.h
new file mode 100644
index 0000000..f1990c7
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/Command.h
@@ -0,0 +1,461 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include <wpi/SmallPtrSet.h>
+#include <wpi/Twine.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/commands/Subsystem.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class CommandGroup;
+
+/**
+ * The Command class is at the very core of the entire command framework.
+ *
+ * Every command can be started with a call to Start(). Once a command is
+ * started it will call Initialize(), and then will repeatedly call Execute()
+ * until the IsFinished() returns true. Once it does,End() will be called.
+ *
+ * However, if at any point while it is running Cancel() is called, then the
+ * command will be stopped and Interrupted() will be called.
+ *
+ * If a command uses a Subsystem, then it should specify that it does so by
+ * calling the Requires() method in its constructor. Note that a Command may
+ * have multiple requirements, and Requires() should be called for each one.
+ *
+ * If a command is running and a new command with shared requirements is
+ * started, then one of two things will happen. If the active command is
+ * interruptible, then Cancel() will be called and the command will be removed
+ * to make way for the new one. If the active command is not interruptible, the
+ * other one will not even be started, and the active one will continue
+ * functioning.
+ *
+ * @see CommandGroup
+ * @see Subsystem
+ */
+class Command : public ErrorBase, public SendableBase {
+ friend class CommandGroup;
+ friend class Scheduler;
+
+ public:
+ /**
+ * Creates a new command.
+ *
+ * The name of this command will be default.
+ */
+ Command();
+
+ /**
+ * Creates a new command with the given name and no timeout.
+ *
+ * @param name the name for this command
+ */
+ explicit Command(const wpi::Twine& name);
+
+ /**
+ * Creates a new command with the given timeout and a default name.
+ *
+ * @param timeout the time (in seconds) before this command "times out"
+ * @see IsTimedOut()
+ */
+ explicit Command(double timeout);
+
+ /**
+ * Creates a new command with the given timeout and a default name.
+ *
+ * @param subsystem the subsystem that the command requires
+ */
+ explicit Command(Subsystem& subsystem);
+
+ /**
+ * Creates a new command with the given name and timeout.
+ *
+ * @param name the name of the command
+ * @param timeout the time (in seconds) before this command "times out"
+ * @see IsTimedOut()
+ */
+ Command(const wpi::Twine& name, double timeout);
+
+ /**
+ * Creates a new command with the given name and timeout.
+ *
+ * @param name the name of the command
+ * @param subsystem the subsystem that the command requires
+ */
+ Command(const wpi::Twine& name, Subsystem& subsystem);
+
+ /**
+ * Creates a new command with the given name and timeout.
+ *
+ * @param timeout the time (in seconds) before this command "times out"
+ * @param subsystem the subsystem that the command requires @see IsTimedOut()
+ */
+ Command(double timeout, Subsystem& subsystem);
+
+ /**
+ * Creates a new command with the given name and timeout.
+ *
+ * @param name the name of the command
+ * @param timeout the time (in seconds) before this command "times out"
+ * @param subsystem the subsystem that the command requires @see IsTimedOut()
+ */
+ Command(const wpi::Twine& name, double timeout, Subsystem& subsystem);
+
+ ~Command() override = default;
+
+ Command(Command&&) = default;
+ Command& operator=(Command&&) = default;
+
+ /**
+ * Returns the time since this command was initialized (in seconds).
+ *
+ * This function will work even if there is no specified timeout.
+ *
+ * @return the time since this command was initialized (in seconds).
+ */
+ double TimeSinceInitialized() const;
+
+ /**
+ * This method specifies that the given Subsystem is used by this command.
+ *
+ * This method is crucial to the functioning of the Command System in general.
+ *
+ * Note that the recommended way to call this method is in the constructor.
+ *
+ * @param subsystem The Subsystem required
+ * @see Subsystem
+ */
+ void Requires(Subsystem* s);
+
+ /**
+ * Starts up the command. Gets the command ready to start.
+ *
+ * Note that the command will eventually start, however it will not
+ * necessarily do so immediately, and may in fact be canceled before
+ * initialize is even called.
+ */
+ void Start();
+
+ /**
+ * The run method is used internally to actually run the commands.
+ *
+ * @return Whether or not the command should stay within the Scheduler.
+ */
+ bool Run();
+
+ /**
+ * This will cancel the current command.
+ *
+ * This will cancel the current command eventually. It can be called multiple
+ * times. And it can be called when the command is not running. If the command
+ * is running though, then the command will be marked as canceled and
+ * eventually removed.
+ *
+ * A command can not be canceled if it is a part of a command group, you must
+ * cancel the command group instead.
+ */
+ void Cancel();
+
+ /**
+ * Returns whether or not the command is running.
+ *
+ * This may return true even if the command has just been canceled, as it may
+ * not have yet called Interrupted().
+ *
+ * @return whether or not the command is running
+ */
+ bool IsRunning() const;
+
+ /**
+ * Returns whether or not the command has been initialized.
+ *
+ * @return whether or not the command has been initialized.
+ */
+ bool IsInitialized() const;
+
+ /**
+ * Returns whether or not the command has completed running.
+ *
+ * @return whether or not the command has completed running.
+ */
+ bool IsCompleted() const;
+
+ /**
+ * Returns whether or not this has been canceled.
+ *
+ * @return whether or not this has been canceled
+ */
+ bool IsCanceled() const;
+
+ /**
+ * Returns whether or not this command can be interrupted.
+ *
+ * @return whether or not this command can be interrupted
+ */
+ bool IsInterruptible() const;
+
+ /**
+ * Sets whether or not this command can be interrupted.
+ *
+ * @param interruptible whether or not this command can be interrupted
+ */
+ void SetInterruptible(bool interruptible);
+
+ /**
+ * Checks if the command requires the given Subsystem.
+ *
+ * @param system the system
+ * @return whether or not the subsystem is required (false if given nullptr)
+ */
+ bool DoesRequire(Subsystem* subsystem) const;
+
+ using SubsystemSet = wpi::SmallPtrSetImpl<Subsystem*>;
+
+ /**
+ * Returns the requirements (as an std::set of Subsystem pointers) of this
+ * command.
+ *
+ * @return The requirements (as an std::set of Subsystem pointers) of this
+ * command
+ */
+ const SubsystemSet& GetRequirements() const;
+
+ /**
+ * Returns the CommandGroup that this command is a part of.
+ *
+ * Will return null if this Command is not in a group.
+ *
+ * @return The CommandGroup that this command is a part of (or null if not in
+ * group)
+ */
+ CommandGroup* GetGroup() const;
+
+ /**
+ * Sets whether or not this Command should run when the robot is disabled.
+ *
+ * By default a command will not run when the robot is disabled, and will in
+ * fact be canceled.
+ *
+ * @param run Whether this command should run when the robot is disabled.
+ */
+ void SetRunWhenDisabled(bool run);
+
+ /**
+ * Returns whether or not this Command will run when the robot is disabled, or
+ * if it will cancel itself.
+ *
+ * @return Whether this Command will run when the robot is disabled, or if it
+ * will cancel itself.
+ */
+ bool WillRunWhenDisabled() const;
+
+ /**
+ * Get the ID (sequence number) for this command.
+ *
+ * The ID is a unique sequence number that is incremented for each command.
+ *
+ * @return The ID of this command
+ */
+ int GetID() const;
+
+ protected:
+ /**
+ * Sets the timeout of this command.
+ *
+ * @param timeout the timeout (in seconds)
+ * @see IsTimedOut()
+ */
+ void SetTimeout(double timeout);
+
+ /**
+ * Returns whether or not the TimeSinceInitialized() method returns a number
+ * which is greater than or equal to the timeout for the command.
+ *
+ * If there is no timeout, this will always return false.
+ *
+ * @return whether the time has expired
+ */
+ bool IsTimedOut() const;
+
+ /**
+ * If changes are locked, then this will generate a CommandIllegalUse error.
+ *
+ * @param message The message to report on error (it is appended by a default
+ * message)
+ * @return True if assert passed, false if assert failed.
+ */
+ bool AssertUnlocked(const std::string& message);
+
+ /**
+ * Sets the parent of this command. No actual change is made to the group.
+ *
+ * @param parent the parent
+ */
+ void SetParent(CommandGroup* parent);
+
+ /**
+ * Returns whether the command has a parent.
+ *
+ * @param True if the command has a parent.
+ */
+ bool IsParented() const;
+
+ /**
+ * Clears list of subsystem requirements.
+ *
+ * This is only used by ConditionalCommand so cancelling the chosen command
+ * works properly in CommandGroup.
+ */
+ void ClearRequirements();
+
+ /**
+ * The initialize method is called the first time this Command is run after
+ * being started.
+ */
+ virtual void Initialize();
+
+ /**
+ * The execute method is called repeatedly until this Command either finishes
+ * or is canceled.
+ */
+ virtual void Execute();
+
+ /**
+ * Returns whether this command is finished.
+ *
+ * If it is, then the command will be removed and End() will be called.
+ *
+ * It may be useful for a team to reference the IsTimedOut() method for
+ * time-sensitive commands.
+ *
+ * Returning false will result in the command never ending automatically.
+ * It may still be cancelled manually or interrupted by another command.
+ * Returning true will result in the command executing once and finishing
+ * immediately. We recommend using InstantCommand for this.
+ *
+ * @return Whether this command is finished.
+ * @see IsTimedOut()
+ */
+ virtual bool IsFinished() = 0;
+
+ /**
+ * Called when the command ended peacefully.
+ *
+ * This is where you may want to wrap up loose ends, like shutting off a motor
+ * that was being used in the command.
+ */
+ virtual void End();
+
+ /**
+ * Called when the command ends because somebody called Cancel() or another
+ * command shared the same requirements as this one, and booted it out.
+ *
+ * This is where you may want to wrap up loose ends, like shutting off a motor
+ * that was being used in the command.
+ *
+ * Generally, it is useful to simply call the End() method within this method,
+ * as done here.
+ */
+ virtual void Interrupted();
+
+ virtual void _Initialize();
+ virtual void _Interrupted();
+ virtual void _Execute();
+ virtual void _End();
+
+ /**
+ * This works like Cancel(), except that it doesn't throw an exception if it
+ * is a part of a command group.
+ *
+ * Should only be called by the parent command group.
+ */
+ virtual void _Cancel();
+
+ friend class ConditionalCommand;
+
+ private:
+ /**
+ * Prevents further changes from being made.
+ */
+ void LockChanges();
+
+ /**
+ * Called when the command has been removed.
+ *
+ * This will call Interrupted() or End().
+ */
+ void Removed();
+
+ /**
+ * This is used internally to mark that the command has been started.
+ *
+ * The lifecycle of a command is:
+ *
+ * StartRunning() is called. Run() is called (multiple times potentially).
+ * Removed() is called.
+ *
+ * It is very important that StartRunning() and Removed() be called in order
+ * or some assumptions of the code will be broken.
+ */
+ void StartRunning();
+
+ /**
+ * Called to indicate that the timer should start.
+ *
+ * This is called right before Initialize() is, inside the Run() method.
+ */
+ void StartTiming();
+
+ // The time since this command was initialized
+ double m_startTime = -1;
+
+ // The time (in seconds) before this command "times out" (-1 if no timeout)
+ double m_timeout;
+
+ // Whether or not this command has been initialized
+ bool m_initialized = false;
+
+ // The requirements (or null if no requirements)
+ wpi::SmallPtrSet<Subsystem*, 4> m_requirements;
+
+ // Whether or not it is running
+ bool m_running = false;
+
+ // Whether or not it is interruptible
+ bool m_interruptible = true;
+
+ // Whether or not it has been canceled
+ bool m_canceled = false;
+
+ // Whether or not it has been locked
+ bool m_locked = false;
+
+ // Whether this command should run when the robot is disabled
+ bool m_runWhenDisabled = false;
+
+ // The CommandGroup this is in
+ CommandGroup* m_parent = nullptr;
+
+ // Whether or not this command has completed running
+ bool m_completed = false;
+
+ int m_commandID = m_commandCounter++;
+ static int m_commandCounter;
+
+ public:
+ void InitSendable(SendableBuilder& builder) override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/CommandGroup.h b/wpilibc/src/main/native/include/frc/commands/CommandGroup.h
new file mode 100644
index 0000000..690ae6d
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/CommandGroup.h
@@ -0,0 +1,180 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <vector>
+
+#include <wpi/Twine.h>
+
+#include "frc/commands/Command.h"
+#include "frc/commands/CommandGroupEntry.h"
+
+namespace frc {
+
+/**
+ * A CommandGroup is a list of commands which are executed in sequence.
+ *
+ * Commands in a CommandGroup are added using the AddSequential() method and are
+ * called sequentially. CommandGroups are themselves Commands and can be given
+ * to other CommandGroups.
+ *
+ * CommandGroups will carry all of the requirements of their Command
+ * subcommands. Additional requirements can be specified by calling Requires()
+ * normally in the constructor.
+ *
+ * CommandGroups can also execute commands in parallel, simply by adding them
+ * using AddParallel().
+ *
+ * @see Command
+ * @see Subsystem
+ */
+class CommandGroup : public Command {
+ public:
+ CommandGroup() = default;
+
+ /**
+ * Creates a new CommandGroup with the given name.
+ *
+ * @param name The name for this command group
+ */
+ explicit CommandGroup(const wpi::Twine& name);
+
+ virtual ~CommandGroup() = default;
+
+ CommandGroup(CommandGroup&&) = default;
+ CommandGroup& operator=(CommandGroup&&) = default;
+
+ /**
+ * Adds a new Command to the group. The Command will be started after all the
+ * previously added Commands.
+ *
+ * Note that any requirements the given Command has will be added to the
+ * group. For this reason, a Command's requirements can not be changed after
+ * being added to a group.
+ *
+ * It is recommended that this method be called in the constructor.
+ *
+ * @param command The Command to be added
+ */
+ void AddSequential(Command* command);
+
+ /**
+ * Adds a new Command to the group with a given timeout. The Command will be
+ * started after all the previously added commands.
+ *
+ * Once the Command is started, it will be run until it finishes or the time
+ * expires, whichever is sooner. Note that the given Command will have no
+ * knowledge that it is on a timer.
+ *
+ * Note that any requirements the given Command has will be added to the
+ * group. For this reason, a Command's requirements can not be changed after
+ * being added to a group.
+ *
+ * It is recommended that this method be called in the constructor.
+ *
+ * @param command The Command to be added
+ * @param timeout The timeout (in seconds)
+ */
+ void AddSequential(Command* command, double timeout);
+
+ /**
+ * Adds a new child Command to the group. The Command will be started after
+ * all the previously added Commands.
+ *
+ * Instead of waiting for the child to finish, a CommandGroup will have it run
+ * at the same time as the subsequent Commands. The child will run until
+ * either it finishes, a new child with conflicting requirements is started,
+ * or the main sequence runs a Command with conflicting requirements. In the
+ * latter two cases, the child will be canceled even if it says it can't be
+ * interrupted.
+ *
+ * Note that any requirements the given Command has will be added to the
+ * group. For this reason, a Command's requirements can not be changed after
+ * being added to a group.
+ *
+ * It is recommended that this method be called in the constructor.
+ *
+ * @param command The command to be added
+ */
+ void AddParallel(Command* command);
+
+ /**
+ * Adds a new child Command to the group with the given timeout. The Command
+ * will be started after all the previously added Commands.
+ *
+ * Once the Command is started, it will run until it finishes, is interrupted,
+ * or the time expires, whichever is sooner. Note that the given Command will
+ * have no knowledge that it is on a timer.
+ *
+ * Instead of waiting for the child to finish, a CommandGroup will have it run
+ * at the same time as the subsequent Commands. The child will run until
+ * either it finishes, the timeout expires, a new child with conflicting
+ * requirements is started, or the main sequence runs a Command with
+ * conflicting requirements. In the latter two cases, the child will be
+ * canceled even if it says it can't be interrupted.
+ *
+ * Note that any requirements the given Command has will be added to the
+ * group. For this reason, a Command's requirements can not be changed after
+ * being added to a group.
+ *
+ * It is recommended that this method be called in the constructor.
+ *
+ * @param command The command to be added
+ * @param timeout The timeout (in seconds)
+ */
+ void AddParallel(Command* command, double timeout);
+
+ bool IsInterruptible() const;
+
+ int GetSize() const;
+
+ protected:
+ /**
+ * Can be overridden by teams.
+ */
+ virtual void Initialize();
+
+ /**
+ * Can be overridden by teams.
+ */
+ virtual void Execute();
+
+ /**
+ * Can be overridden by teams.
+ */
+ virtual bool IsFinished();
+
+ /**
+ * Can be overridden by teams.
+ */
+ virtual void End();
+
+ /**
+ * Can be overridden by teams.
+ */
+ virtual void Interrupted();
+
+ virtual void _Initialize();
+ virtual void _Execute();
+ virtual void _End();
+ virtual void _Interrupted();
+
+ private:
+ void CancelConflicts(Command* command);
+
+ // The commands in this group (stored in entries)
+ std::vector<CommandGroupEntry> m_commands;
+
+ // The active children in this group (stored in entries)
+ std::vector<CommandGroupEntry*> m_children;
+
+ // The current command, -1 signifies that none have been run
+ int m_currentCommandIndex = -1;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/CommandGroupEntry.h b/wpilibc/src/main/native/include/frc/commands/CommandGroupEntry.h
new file mode 100644
index 0000000..2de1e43
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/CommandGroupEntry.h
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+class Command;
+
+class CommandGroupEntry {
+ public:
+ enum Sequence {
+ kSequence_InSequence,
+ kSequence_BranchPeer,
+ kSequence_BranchChild
+ };
+
+ CommandGroupEntry() = default;
+ CommandGroupEntry(Command* command, Sequence state, double timeout = -1.0);
+
+ CommandGroupEntry(CommandGroupEntry&&) = default;
+ CommandGroupEntry& operator=(CommandGroupEntry&&) = default;
+
+ bool IsTimedOut() const;
+
+ double m_timeout = -1.0;
+ Command* m_command = nullptr;
+ Sequence m_state = kSequence_InSequence;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/ConditionalCommand.h b/wpilibc/src/main/native/include/frc/commands/ConditionalCommand.h
new file mode 100644
index 0000000..142c5b0
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/ConditionalCommand.h
@@ -0,0 +1,84 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/Twine.h>
+
+#include "frc/commands/Command.h"
+
+namespace frc {
+
+/**
+ * A ConditionalCommand is a Command that starts one of two commands.
+ *
+ * A ConditionalCommand uses the Condition method to determine whether it should
+ * run onTrue or onFalse.
+ *
+ * A ConditionalCommand adds the proper Command to the Scheduler during
+ * Initialize() and then IsFinished() will return true once that Command has
+ * finished executing.
+ *
+ * If no Command is specified for onFalse, the occurrence of that condition
+ * will be a no-op.
+ *
+ * A CondtionalCommand will require the superset of subsystems of the onTrue
+ * and onFalse commands.
+ *
+ * @see Command
+ * @see Scheduler
+ */
+class ConditionalCommand : public Command {
+ public:
+ /**
+ * Creates a new ConditionalCommand with given onTrue and onFalse Commands.
+ *
+ * @param onTrue The Command to execute if Condition() returns true
+ * @param onFalse The Command to execute if Condition() returns false
+ */
+ explicit ConditionalCommand(Command* onTrue, Command* onFalse = nullptr);
+
+ /**
+ * Creates a new ConditionalCommand with given onTrue and onFalse Commands.
+ *
+ * @param name The name for this command group
+ * @param onTrue The Command to execute if Condition() returns true
+ * @param onFalse The Command to execute if Condition() returns false
+ */
+ ConditionalCommand(const wpi::Twine& name, Command* onTrue,
+ Command* onFalse = nullptr);
+
+ virtual ~ConditionalCommand() = default;
+
+ ConditionalCommand(ConditionalCommand&&) = default;
+ ConditionalCommand& operator=(ConditionalCommand&&) = default;
+
+ protected:
+ /**
+ * The Condition to test to determine which Command to run.
+ *
+ * @return true if m_onTrue should be run or false if m_onFalse should be run.
+ */
+ virtual bool Condition() = 0;
+
+ void _Initialize() override;
+ void _Cancel() override;
+ bool IsFinished() override;
+ void _Interrupted() override;
+
+ private:
+ // The Command to execute if Condition() returns true
+ Command* m_onTrue;
+
+ // The Command to execute if Condition() returns false
+ Command* m_onFalse;
+
+ // Stores command chosen by condition
+ Command* m_chosenCommand = nullptr;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/InstantCommand.h b/wpilibc/src/main/native/include/frc/commands/InstantCommand.h
new file mode 100644
index 0000000..987dc18
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/InstantCommand.h
@@ -0,0 +1,93 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <functional>
+
+#include <wpi/Twine.h>
+
+#include "frc/commands/Command.h"
+#include "frc/commands/Subsystem.h"
+
+namespace frc {
+
+/**
+ * This command will execute once, then finish immediately afterward.
+ *
+ * Subclassing InstantCommand is shorthand for returning true from IsFinished().
+ */
+class InstantCommand : public Command {
+ public:
+ /**
+ * Creates a new InstantCommand with the given name.
+ *
+ * @param name The name for this command
+ */
+ explicit InstantCommand(const wpi::Twine& name);
+
+ /**
+ * Creates a new InstantCommand with the given requirement.
+ *
+ * @param subsystem The subsystem that the command requires
+ */
+ explicit InstantCommand(Subsystem& subsystem);
+
+ /**
+ * Creates a new InstantCommand with the given name.
+ *
+ * @param name The name for this command
+ * @param subsystem The subsystem that the command requires
+ */
+ InstantCommand(const wpi::Twine& name, Subsystem& subsystem);
+
+ /**
+ * Create a command that calls the given function when run.
+ *
+ * @param func The function to run when Initialize() is run.
+ */
+ explicit InstantCommand(std::function<void()> func);
+
+ /**
+ * Create a command that calls the given function when run.
+ *
+ * @param subsystem The subsystems that this command runs on.
+ * @param func The function to run when Initialize() is run.
+ */
+ InstantCommand(Subsystem& subsystem, std::function<void()> func);
+
+ /**
+ * Create a command that calls the given function when run.
+ *
+ * @param name The name of the command.
+ * @param func The function to run when Initialize() is run.
+ */
+ InstantCommand(const wpi::Twine& name, std::function<void()> func);
+
+ /**
+ * Create a command that calls the given function when run.
+ *
+ * @param name The name of the command.
+ * @param subsystem The subsystems that this command runs on.
+ * @param func The function to run when Initialize() is run.
+ */
+ InstantCommand(const wpi::Twine& name, Subsystem& subsystem,
+ std::function<void()> func);
+
+ InstantCommand() = default;
+ virtual ~InstantCommand() = default;
+
+ InstantCommand(InstantCommand&&) = default;
+ InstantCommand& operator=(InstantCommand&&) = default;
+
+ protected:
+ std::function<void()> m_func = nullptr;
+ void _Initialize() override;
+ bool IsFinished() override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/PIDCommand.h b/wpilibc/src/main/native/include/frc/commands/PIDCommand.h
new file mode 100644
index 0000000..02f1710
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/PIDCommand.h
@@ -0,0 +1,74 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <wpi/Twine.h>
+
+#include "frc/PIDController.h"
+#include "frc/PIDOutput.h"
+#include "frc/PIDSource.h"
+#include "frc/commands/Command.h"
+
+namespace frc {
+
+class PIDCommand : public Command, public PIDOutput, public PIDSource {
+ public:
+ PIDCommand(const wpi::Twine& name, double p, double i, double d);
+ PIDCommand(const wpi::Twine& name, double p, double i, double d,
+ double period);
+ PIDCommand(const wpi::Twine& name, double p, double i, double d, double f,
+ double period);
+ PIDCommand(double p, double i, double d);
+ PIDCommand(double p, double i, double d, double period);
+ PIDCommand(double p, double i, double d, double f, double period);
+ PIDCommand(const wpi::Twine& name, double p, double i, double d,
+ Subsystem& subsystem);
+ PIDCommand(const wpi::Twine& name, double p, double i, double d,
+ double period, Subsystem& subsystem);
+ PIDCommand(const wpi::Twine& name, double p, double i, double d, double f,
+ double period, Subsystem& subsystem);
+ PIDCommand(double p, double i, double d, Subsystem& subsystem);
+ PIDCommand(double p, double i, double d, double period, Subsystem& subsystem);
+ PIDCommand(double p, double i, double d, double f, double period,
+ Subsystem& subsystem);
+ virtual ~PIDCommand() = default;
+
+ PIDCommand(PIDCommand&&) = default;
+ PIDCommand& operator=(PIDCommand&&) = default;
+
+ void SetSetpointRelative(double deltaSetpoint);
+
+ // PIDOutput interface
+ void PIDWrite(double output) override;
+
+ // PIDSource interface
+ double PIDGet() override;
+
+ protected:
+ std::shared_ptr<PIDController> GetPIDController() const;
+ void _Initialize() override;
+ void _Interrupted() override;
+ void _End() override;
+ void SetSetpoint(double setpoint);
+ double GetSetpoint() const;
+ double GetPosition();
+
+ virtual double ReturnPIDInput() = 0;
+ virtual void UsePIDOutput(double output) = 0;
+
+ private:
+ // The internal PIDController
+ std::shared_ptr<PIDController> m_controller;
+
+ public:
+ void InitSendable(SendableBuilder& builder) override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/PIDSubsystem.h b/wpilibc/src/main/native/include/frc/commands/PIDSubsystem.h
new file mode 100644
index 0000000..1965492
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/PIDSubsystem.h
@@ -0,0 +1,236 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <wpi/Twine.h>
+
+#include "frc/PIDController.h"
+#include "frc/PIDOutput.h"
+#include "frc/PIDSource.h"
+#include "frc/commands/Subsystem.h"
+
+namespace frc {
+
+/**
+ * This class is designed to handle the case where there is a Subsystem which
+ * uses a single PIDController almost constantly (for instance, an elevator
+ * which attempts to stay at a constant height).
+ *
+ * It provides some convenience methods to run an internal PIDController. It
+ * also allows access to the internal PIDController in order to give total
+ * control to the programmer.
+ */
+class PIDSubsystem : public Subsystem, public PIDOutput, public PIDSource {
+ public:
+ /**
+ * Instantiates a PIDSubsystem that will use the given P, I, and D values.
+ *
+ * @param name the name
+ * @param p the proportional value
+ * @param i the integral value
+ * @param d the derivative value
+ */
+ PIDSubsystem(const wpi::Twine& name, double p, double i, double d);
+
+ /**
+ * Instantiates a PIDSubsystem that will use the given P, I, and D values.
+ *
+ * @param name the name
+ * @param p the proportional value
+ * @param i the integral value
+ * @param d the derivative value
+ * @param f the feedforward value
+ */
+ PIDSubsystem(const wpi::Twine& name, double p, double i, double d, double f);
+
+ /**
+ * Instantiates a PIDSubsystem that will use the given P, I, and D values.
+ *
+ * It will also space the time between PID loop calculations to be equal to
+ * the given period.
+ *
+ * @param name the name
+ * @param p the proportional value
+ * @param i the integral value
+ * @param d the derivative value
+ * @param f the feedfoward value
+ * @param period the time (in seconds) between calculations
+ */
+ PIDSubsystem(const wpi::Twine& name, double p, double i, double d, double f,
+ double period);
+
+ /**
+ * Instantiates a PIDSubsystem that will use the given P, I, and D values.
+ *
+ * It will use the class name as its name.
+ *
+ * @param p the proportional value
+ * @param i the integral value
+ * @param d the derivative value
+ */
+ PIDSubsystem(double p, double i, double d);
+
+ /**
+ * Instantiates a PIDSubsystem that will use the given P, I, and D values.
+ *
+ * It will use the class name as its name.
+ *
+ * @param p the proportional value
+ * @param i the integral value
+ * @param d the derivative value
+ * @param f the feedforward value
+ */
+ PIDSubsystem(double p, double i, double d, double f);
+
+ /**
+ * Instantiates a PIDSubsystem that will use the given P, I, and D values.
+ *
+ * It will use the class name as its name. It will also space the time
+ * between PID loop calculations to be equal to the given period.
+ *
+ * @param p the proportional value
+ * @param i the integral value
+ * @param d the derivative value
+ * @param f the feedforward value
+ * @param period the time (in seconds) between calculations
+ */
+ PIDSubsystem(double p, double i, double d, double f, double period);
+
+ ~PIDSubsystem() override = default;
+
+ PIDSubsystem(PIDSubsystem&&) = default;
+ PIDSubsystem& operator=(PIDSubsystem&&) = default;
+
+ /**
+ * Enables the internal PIDController.
+ */
+ void Enable();
+
+ /**
+ * Disables the internal PIDController.
+ */
+ void Disable();
+
+ // PIDOutput interface
+ void PIDWrite(double output) override;
+
+ // PIDSource interface
+
+ double PIDGet() override;
+
+ /**
+ * Sets the setpoint to the given value.
+ *
+ * If SetRange() was called, then the given setpoint will be trimmed to fit
+ * within the range.
+ *
+ * @param setpoint the new setpoint
+ */
+ void SetSetpoint(double setpoint);
+
+ /**
+ * Adds the given value to the setpoint.
+ *
+ * If SetRange() was used, then the bounds will still be honored by this
+ * method.
+ *
+ * @param deltaSetpoint the change in the setpoint
+ */
+ void SetSetpointRelative(double deltaSetpoint);
+
+ /**
+ * Sets the maximum and minimum values expected from the input.
+ *
+ * @param minimumInput the minimum value expected from the input
+ * @param maximumInput the maximum value expected from the output
+ */
+ void SetInputRange(double minimumInput, double maximumInput);
+
+ /**
+ * Sets the maximum and minimum values to write.
+ *
+ * @param minimumOutput the minimum value to write to the output
+ * @param maximumOutput the maximum value to write to the output
+ */
+ void SetOutputRange(double minimumOutput, double maximumOutput);
+
+ /**
+ * Return the current setpoint.
+ *
+ * @return The current setpoint
+ */
+ double GetSetpoint();
+
+ /**
+ * Returns the current position.
+ *
+ * @return the current position
+ */
+ double GetPosition();
+
+ /**
+ * Returns the current rate.
+ *
+ * @return the current rate
+ */
+ double GetRate();
+
+ /**
+ * Set the absolute error which is considered tolerable for use with
+ * OnTarget.
+ *
+ * @param absValue absolute error which is tolerable
+ */
+ virtual void SetAbsoluteTolerance(double absValue);
+
+ /**
+ * Set the percentage error which is considered tolerable for use with
+ * OnTarget().
+ *
+ * @param percent percentage error which is tolerable
+ */
+ virtual void SetPercentTolerance(double percent);
+
+ /**
+ * Return true if the error is within the percentage of the total input range,
+ * determined by SetTolerance().
+ *
+ * This asssumes that the maximum and minimum input were set using SetInput().
+ * Use OnTarget() in the IsFinished() method of commands that use this
+ * subsystem.
+ *
+ * Currently this just reports on target as the actual value passes through
+ * the setpoint. Ideally it should be based on being within the tolerance for
+ * some period of time.
+ *
+ * @return True if the error is within the percentage tolerance of the input
+ * range
+ */
+ virtual bool OnTarget() const;
+
+ protected:
+ /**
+ * Returns the PIDController used by this PIDSubsystem.
+ *
+ * Use this if you would like to fine tune the PID loop.
+ *
+ * @return The PIDController used by this PIDSubsystem
+ */
+ std::shared_ptr<PIDController> GetPIDController();
+
+ virtual double ReturnPIDInput() = 0;
+ virtual void UsePIDOutput(double output) = 0;
+
+ private:
+ // The internal PIDController
+ std::shared_ptr<PIDController> m_controller;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/PrintCommand.h b/wpilibc/src/main/native/include/frc/commands/PrintCommand.h
new file mode 100644
index 0000000..13156c9
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/PrintCommand.h
@@ -0,0 +1,33 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <string>
+
+#include <wpi/Twine.h>
+
+#include "frc/commands/InstantCommand.h"
+
+namespace frc {
+
+class PrintCommand : public InstantCommand {
+ public:
+ explicit PrintCommand(const wpi::Twine& message);
+ virtual ~PrintCommand() = default;
+
+ PrintCommand(PrintCommand&&) = default;
+ PrintCommand& operator=(PrintCommand&&) = default;
+
+ protected:
+ virtual void Initialize();
+
+ private:
+ std::string m_message;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/Scheduler.h b/wpilibc/src/main/native/include/frc/commands/Scheduler.h
new file mode 100644
index 0000000..c5c97ba
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/Scheduler.h
@@ -0,0 +1,97 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include "frc/ErrorBase.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class ButtonScheduler;
+class Command;
+class Subsystem;
+
+class Scheduler : public ErrorBase, public SendableBase {
+ public:
+ /**
+ * Returns the Scheduler, creating it if one does not exist.
+ *
+ * @return the Scheduler
+ */
+ static Scheduler* GetInstance();
+
+ /**
+ * Add a command to be scheduled later.
+ *
+ * In any pass through the scheduler, all commands are added to the additions
+ * list, then at the end of the pass, they are all scheduled.
+ *
+ * @param command The command to be scheduled
+ */
+ void AddCommand(Command* command);
+
+ void AddButton(ButtonScheduler* button);
+
+ /**
+ * Registers a Subsystem to this Scheduler, so that the Scheduler might know
+ * if a default Command needs to be run.
+ *
+ * All Subsystems should call this.
+ *
+ * @param system the system
+ */
+ void RegisterSubsystem(Subsystem* subsystem);
+
+ /**
+ * Runs a single iteration of the loop.
+ *
+ * This method should be called often in order to have a functioning
+ * Command system. The loop has five stages:
+ *
+ * <ol>
+ * <li>Poll the Buttons</li>
+ * <li>Execute/Remove the Commands</li>
+ * <li>Send values to SmartDashboard</li>
+ * <li>Add Commands</li>
+ * <li>Add Defaults</li>
+ * </ol>
+ */
+ void Run();
+
+ /**
+ * Removes the Command from the Scheduler.
+ *
+ * @param command the command to remove
+ */
+ void Remove(Command* command);
+
+ void RemoveAll();
+
+ /**
+ * Completely resets the scheduler. Undefined behavior if running.
+ */
+ void ResetAll();
+
+ void SetEnabled(bool enabled);
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ Scheduler();
+ ~Scheduler() override;
+
+ Scheduler(Scheduler&&) = default;
+ Scheduler& operator=(Scheduler&&) = default;
+
+ struct Impl;
+ std::unique_ptr<Impl> m_impl;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/StartCommand.h b/wpilibc/src/main/native/include/frc/commands/StartCommand.h
new file mode 100644
index 0000000..4f0b676
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/StartCommand.h
@@ -0,0 +1,29 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/commands/InstantCommand.h"
+
+namespace frc {
+
+class StartCommand : public InstantCommand {
+ public:
+ explicit StartCommand(Command* commandToStart);
+ virtual ~StartCommand() = default;
+
+ StartCommand(StartCommand&&) = default;
+ StartCommand& operator=(StartCommand&&) = default;
+
+ protected:
+ virtual void Initialize();
+
+ private:
+ Command* m_commandToFork;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/Subsystem.h b/wpilibc/src/main/native/include/frc/commands/Subsystem.h
new file mode 100644
index 0000000..bb6d166
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/Subsystem.h
@@ -0,0 +1,168 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <wpi/StringRef.h>
+#include <wpi/Twine.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/smartdashboard/Sendable.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class Command;
+
+class Subsystem : public ErrorBase, public SendableBase {
+ friend class Scheduler;
+
+ public:
+ /**
+ * Creates a subsystem with the given name.
+ *
+ * @param name the name of the subsystem
+ */
+ explicit Subsystem(const wpi::Twine& name);
+
+ Subsystem(Subsystem&&) = default;
+ Subsystem& operator=(Subsystem&&) = default;
+
+ /**
+ * Sets the default command. If this is not called or is called with null,
+ * then there will be no default command for the subsystem.
+ *
+ * <b>WARNING:</b> This should <b>NOT</b> be called in a constructor if the
+ * subsystem is a singleton.
+ *
+ * @param command the default command (or null if there should be none)
+ */
+ void SetDefaultCommand(Command* command);
+
+ /**
+ * Returns the default command (or null if there is none).
+ *
+ * @return the default command
+ */
+ Command* GetDefaultCommand();
+
+ /**
+ * Returns the default command name, or empty string is there is none.
+ *
+ * @return the default command name
+ */
+ wpi::StringRef GetDefaultCommandName();
+
+ /**
+ * Sets the current command.
+ *
+ * @param command the new current command
+ */
+ void SetCurrentCommand(Command* command);
+
+ /**
+ * Returns the command which currently claims this subsystem.
+ *
+ * @return the command which currently claims this subsystem
+ */
+ Command* GetCurrentCommand() const;
+
+ /**
+ * Returns the current command name, or empty string if no current command.
+ *
+ * @return the current command name
+ */
+ wpi::StringRef GetCurrentCommandName() const;
+
+ /**
+ * When the run method of the scheduler is called this method will be called.
+ */
+ virtual void Periodic();
+
+ /**
+ * Initialize the default command for this subsystem.
+ *
+ * This is meant to be the place to call SetDefaultCommand in a subsystem and
+ * will be called on all the subsystems by the CommandBase method before the
+ * program starts running by using the list of all registered Subsystems
+ * inside the Scheduler.
+ *
+ * This should be overridden by a Subsystem that has a default Command
+ */
+ virtual void InitDefaultCommand();
+
+ /**
+ * Associate a Sendable with this Subsystem.
+ * Also update the child's name.
+ *
+ * @param name name to give child
+ * @param child sendable
+ */
+ void AddChild(const wpi::Twine& name, std::shared_ptr<Sendable> child);
+
+ /**
+ * Associate a Sendable with this Subsystem.
+ * Also update the child's name.
+ *
+ * @param name name to give child
+ * @param child sendable
+ */
+ void AddChild(const wpi::Twine& name, Sendable* child);
+
+ /**
+ * Associate a Sendable with this Subsystem.
+ * Also update the child's name.
+ *
+ * @param name name to give child
+ * @param child sendable
+ */
+ void AddChild(const wpi::Twine& name, Sendable& child);
+
+ /**
+ * Associate a {@link Sendable} with this Subsystem.
+ *
+ * @param child sendable
+ */
+ void AddChild(std::shared_ptr<Sendable> child);
+
+ /**
+ * Associate a {@link Sendable} with this Subsystem.
+ *
+ * @param child sendable
+ */
+ void AddChild(Sendable* child);
+
+ /**
+ * Associate a {@link Sendable} with this Subsystem.
+ *
+ * @param child sendable
+ */
+ void AddChild(Sendable& child);
+
+ private:
+ /**
+ * Call this to alert Subsystem that the current command is actually the
+ * command.
+ *
+ * Sometimes, the Subsystem is told that it has no command while the Scheduler
+ * is going through the loop, only to be soon after given a new one. This will
+ * avoid that situation.
+ */
+ void ConfirmCommand();
+
+ Command* m_currentCommand = nullptr;
+ bool m_currentCommandChanged = true;
+ Command* m_defaultCommand = nullptr;
+ bool m_initializedDefaultCommand = false;
+
+ public:
+ void InitSendable(SendableBuilder& builder) override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/TimedCommand.h b/wpilibc/src/main/native/include/frc/commands/TimedCommand.h
new file mode 100644
index 0000000..d2be010
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/TimedCommand.h
@@ -0,0 +1,67 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/Twine.h>
+
+#include "frc/commands/Command.h"
+
+namespace frc {
+
+/**
+ * A TimedCommand will wait for a timeout before finishing.
+ *
+ * TimedCommand is used to execute a command for a given amount of time.
+ */
+class TimedCommand : public Command {
+ public:
+ /**
+ * Creates a new TimedCommand with the given name and timeout.
+ *
+ * @param name the name of the command
+ * @param timeout the time (in seconds) before this command "times out"
+ */
+ TimedCommand(const wpi::Twine& name, double timeout);
+
+ /**
+ * Creates a new WaitCommand with the given timeout.
+ *
+ * @param timeout the time (in seconds) before this command "times out"
+ */
+ explicit TimedCommand(double timeout);
+
+ /**
+ * Creates a new TimedCommand with the given name and timeout.
+ *
+ * @param name the name of the command
+ * @param timeout the time (in seconds) before this command "times out"
+ * @param subsystem the subsystem that the command requires
+ */
+ TimedCommand(const wpi::Twine& name, double timeout, Subsystem& subsystem);
+
+ /**
+ * Creates a new WaitCommand with the given timeout.
+ *
+ * @param timeout the time (in seconds) before this command "times out"
+ * @param subsystem the subsystem that the command requires
+ */
+ TimedCommand(double timeout, Subsystem& subsystem);
+
+ virtual ~TimedCommand() = default;
+
+ TimedCommand(TimedCommand&&) = default;
+ TimedCommand& operator=(TimedCommand&&) = default;
+
+ protected:
+ /**
+ * Ends command when timed out.
+ */
+ bool IsFinished() override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/WaitCommand.h b/wpilibc/src/main/native/include/frc/commands/WaitCommand.h
new file mode 100644
index 0000000..481b1c6
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/WaitCommand.h
@@ -0,0 +1,39 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/Twine.h>
+
+#include "frc/commands/TimedCommand.h"
+
+namespace frc {
+
+class WaitCommand : public TimedCommand {
+ public:
+ /**
+ * Creates a new WaitCommand with the given name and timeout.
+ *
+ * @param name the name of the command
+ * @param timeout the time (in seconds) before this command "times out"
+ */
+ explicit WaitCommand(double timeout);
+
+ /**
+ * Creates a new WaitCommand with the given timeout.
+ *
+ * @param timeout the time (in seconds) before this command "times out"
+ */
+ WaitCommand(const wpi::Twine& name, double timeout);
+
+ virtual ~WaitCommand() = default;
+
+ WaitCommand(WaitCommand&&) = default;
+ WaitCommand& operator=(WaitCommand&&) = default;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/WaitForChildren.h b/wpilibc/src/main/native/include/frc/commands/WaitForChildren.h
new file mode 100644
index 0000000..6f2e285
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/WaitForChildren.h
@@ -0,0 +1,29 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/Twine.h>
+
+#include "frc/commands/Command.h"
+
+namespace frc {
+
+class WaitForChildren : public Command {
+ public:
+ explicit WaitForChildren(double timeout);
+ WaitForChildren(const wpi::Twine& name, double timeout);
+ virtual ~WaitForChildren() = default;
+
+ WaitForChildren(WaitForChildren&&) = default;
+ WaitForChildren& operator=(WaitForChildren&&) = default;
+
+ protected:
+ virtual bool IsFinished();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/commands/WaitUntilCommand.h b/wpilibc/src/main/native/include/frc/commands/WaitUntilCommand.h
new file mode 100644
index 0000000..1231750
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/commands/WaitUntilCommand.h
@@ -0,0 +1,45 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/Twine.h>
+
+#include "frc/commands/Command.h"
+
+namespace frc {
+
+class WaitUntilCommand : public Command {
+ public:
+ /**
+ * A WaitCommand will wait until a certain match time before finishing.
+ *
+ * This will wait until the game clock reaches some value, then continue to
+ * the next command.
+ *
+ * @see CommandGroup
+ */
+ explicit WaitUntilCommand(double time);
+
+ WaitUntilCommand(const wpi::Twine& name, double time);
+
+ virtual ~WaitUntilCommand() = default;
+
+ WaitUntilCommand(WaitUntilCommand&&) = default;
+ WaitUntilCommand& operator=(WaitUntilCommand&&) = default;
+
+ protected:
+ /**
+ * Check if we've reached the actual finish time.
+ */
+ virtual bool IsFinished();
+
+ private:
+ double m_time;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/drive/DifferentialDrive.h b/wpilibc/src/main/native/include/frc/drive/DifferentialDrive.h
new file mode 100644
index 0000000..1120659
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/drive/DifferentialDrive.h
@@ -0,0 +1,220 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/raw_ostream.h>
+
+#include "frc/drive/RobotDriveBase.h"
+
+namespace frc {
+
+class SpeedController;
+
+/**
+ * A class for driving differential drive/skid-steer drive platforms such as
+ * the Kit of Parts drive base, "tank drive", or West Coast Drive.
+ *
+ * These drive bases typically have drop-center / skid-steer with two or more
+ * wheels per side (e.g., 6WD or 8WD). This class takes a SpeedController per
+ * side. For four and six motor drivetrains, construct and pass in
+ * SpeedControllerGroup instances as follows.
+ *
+ * Four motor drivetrain:
+ * @code{.cpp}
+ * class Robot {
+ * public:
+ * frc::Spark m_frontLeft{1};
+ * frc::Spark m_rearLeft{2};
+ * frc::SpeedControllerGroup m_left{m_frontLeft, m_rearLeft};
+ *
+ * frc::Spark m_frontRight{3};
+ * frc::Spark m_rearRight{4};
+ * frc::SpeedControllerGroup m_right{m_frontRight, m_rearRight};
+ *
+ * frc::DifferentialDrive m_drive{m_left, m_right};
+ * };
+ * @endcode
+ *
+ * Six motor drivetrain:
+ * @code{.cpp}
+ * class Robot {
+ * public:
+ * frc::Spark m_frontLeft{1};
+ * frc::Spark m_midLeft{2};
+ * frc::Spark m_rearLeft{3};
+ * frc::SpeedControllerGroup m_left{m_frontLeft, m_midLeft, m_rearLeft};
+ *
+ * frc::Spark m_frontRight{4};
+ * frc::Spark m_midRight{5};
+ * frc::Spark m_rearRight{6};
+ * frc::SpeedControllerGroup m_right{m_frontRight, m_midRight, m_rearRight};
+ *
+ * frc::DifferentialDrive m_drive{m_left, m_right};
+ * };
+ * @endcode
+ *
+ * A differential drive robot has left and right wheels separated by an
+ * arbitrary width.
+ *
+ * Drive base diagram:
+ * <pre>
+ * |_______|
+ * | | | |
+ * | |
+ * |_|___|_|
+ * | |
+ * </pre>
+ *
+ * Each Drive() function provides different inverse kinematic relations for a
+ * differential drive robot. Motor outputs for the right side are negated, so
+ * motor direction inversion by the user is usually unnecessary.
+ *
+ * This library uses the NED axes convention (North-East-Down as external
+ * reference in the world frame):
+ * http://www.nuclearprojects.com/ins/images/axis_big.png.
+ *
+ * The positive X axis points ahead, the positive Y axis points to the right,
+ * and the positive Z axis points down. Rotations follow the right-hand rule, so
+ * clockwise rotation around the Z axis is positive.
+ *
+ * Inputs smaller then 0.02 will be set to 0, and larger values will be scaled
+ * so that the full range is still used. This deadband value can be changed
+ * with SetDeadband().
+ *
+ * <p>RobotDrive porting guide:
+ * <br>TankDrive(double, double, bool) is equivalent to
+ * RobotDrive#TankDrive(double, double, bool) if a deadband of 0 is used.
+ * <br>ArcadeDrive(double, double, bool) is equivalent to
+ * RobotDrive#ArcadeDrive(double, double, bool) if a deadband of 0 is used
+ * and the the rotation input is inverted eg ArcadeDrive(y, -rotation, false)
+ * <br>CurvatureDrive(double, double, bool) is similar in concept to
+ * RobotDrive#Drive(double, double) with the addition of a quick turn
+ * mode. However, it is not designed to give exactly the same response.
+ */
+class DifferentialDrive : public RobotDriveBase {
+ public:
+ static constexpr double kDefaultQuickStopThreshold = 0.2;
+ static constexpr double kDefaultQuickStopAlpha = 0.1;
+
+ /**
+ * Construct a DifferentialDrive.
+ *
+ * To pass multiple motors per side, use a SpeedControllerGroup. If a motor
+ * needs to be inverted, do so before passing it in.
+ */
+ DifferentialDrive(SpeedController& leftMotor, SpeedController& rightMotor);
+
+ ~DifferentialDrive() override = default;
+
+ DifferentialDrive(DifferentialDrive&&) = default;
+ DifferentialDrive& operator=(DifferentialDrive&&) = default;
+
+ /**
+ * Arcade drive method for differential drive platform.
+ *
+ * Note: Some drivers may prefer inverted rotation controls. This can be done
+ * by negating the value passed for rotation.
+ *
+ * @param xSpeed The speed at which the robot should drive along the X
+ * axis [-1.0..1.0]. Forward is negative.
+ * @param zRotation The rotation rate of the robot around the Z axis
+ * [-1.0..1.0]. Clockwise is positive.
+ * @param squareInputs If set, decreases the input sensitivity at low speeds.
+ */
+ void ArcadeDrive(double xSpeed, double zRotation, bool squareInputs = true);
+
+ /**
+ * Curvature drive method for differential drive platform.
+ *
+ * The rotation argument controls the curvature of the robot's path rather
+ * than its rate of heading change. This makes the robot more controllable at
+ * high speeds. Also handles the robot's quick turn functionality - "quick
+ * turn" overrides constant-curvature turning for turn-in-place maneuvers.
+ *
+ * @param xSpeed The robot's speed along the X axis [-1.0..1.0]. Forward
+ * is positive.
+ * @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
+ * Clockwise is positive.
+ * @param isQuickTurn If set, overrides constant-curvature turning for
+ * turn-in-place maneuvers.
+ */
+ void CurvatureDrive(double xSpeed, double zRotation, bool isQuickTurn);
+
+ /**
+ * Tank drive method for differential drive platform.
+ *
+ * @param leftSpeed The robot left side's speed along the X axis
+ * [-1.0..1.0]. Forward is positive.
+ * @param rightSpeed The robot right side's speed along the X axis
+ * [-1.0..1.0]. Forward is positive.
+ * @param squareInputs If set, decreases the input sensitivity at low speeds.
+ */
+ void TankDrive(double leftSpeed, double rightSpeed, bool squareInputs = true);
+
+ /**
+ * Sets the QuickStop speed threshold in curvature drive.
+ *
+ * QuickStop compensates for the robot's moment of inertia when stopping after
+ * a QuickTurn.
+ *
+ * While QuickTurn is enabled, the QuickStop accumulator takes on the rotation
+ * rate value outputted by the low-pass filter when the robot's speed along
+ * the X axis is below the threshold. When QuickTurn is disabled, the
+ * accumulator's value is applied against the computed angular power request
+ * to slow the robot's rotation.
+ *
+ * @param threshold X speed below which quick stop accumulator will receive
+ * rotation rate values [0..1.0].
+ */
+ void SetQuickStopThreshold(double threshold);
+
+ /**
+ * Sets the low-pass filter gain for QuickStop in curvature drive.
+ *
+ * The low-pass filter filters incoming rotation rate commands to smooth out
+ * high frequency changes.
+ *
+ * @param alpha Low-pass filter gain [0.0..2.0]. Smaller values result in
+ * slower output changes. Values between 1.0 and 2.0 result in
+ * output oscillation. Values below 0.0 and above 2.0 are
+ * unstable.
+ */
+ void SetQuickStopAlpha(double alpha);
+
+ /**
+ * Gets if the power sent to the right side of the drivetrain is multipled by
+ * -1.
+ *
+ * @return true if the right side is inverted
+ */
+ bool IsRightSideInverted() const;
+
+ /**
+ * Sets if the power sent to the right side of the drivetrain should be
+ * multipled by -1.
+ *
+ * @param rightSideInverted true if right side power should be multipled by -1
+ */
+ void SetRightSideInverted(bool rightSideInverted);
+
+ void StopMotor() override;
+ void GetDescription(wpi::raw_ostream& desc) const override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ SpeedController& m_leftMotor;
+ SpeedController& m_rightMotor;
+
+ double m_quickStopThreshold = kDefaultQuickStopThreshold;
+ double m_quickStopAlpha = kDefaultQuickStopAlpha;
+ double m_quickStopAccumulator = 0.0;
+ double m_rightSideInvertMultiplier = -1.0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/drive/KilloughDrive.h b/wpilibc/src/main/native/include/frc/drive/KilloughDrive.h
new file mode 100644
index 0000000..2fa356d
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/drive/KilloughDrive.h
@@ -0,0 +1,142 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <wpi/raw_ostream.h>
+
+#include "frc/drive/RobotDriveBase.h"
+#include "frc/drive/Vector2d.h"
+
+namespace frc {
+
+class SpeedController;
+
+/**
+ * A class for driving Killough drive platforms.
+ *
+ * Killough drives are triangular with one omni wheel on each corner.
+ *
+ * Drive base diagram:
+ * <pre>
+ * /_____\
+ * / \ / \
+ * \ /
+ * ---
+ * </pre>
+ *
+ * Each Drive() function provides different inverse kinematic relations for a
+ * Killough drive. The default wheel vectors are parallel to their respective
+ * opposite sides, but can be overridden. See the constructor for more
+ * information.
+ *
+ * This library uses the NED axes convention (North-East-Down as external
+ * reference in the world frame):
+ * http://www.nuclearprojects.com/ins/images/axis_big.png.
+ *
+ * The positive X axis points ahead, the positive Y axis points right, and the
+ * and the positive Z axis points down. Rotations follow the right-hand rule, so
+ * clockwise rotation around the Z axis is positive.
+ */
+class KilloughDrive : public RobotDriveBase {
+ public:
+ static constexpr double kDefaultLeftMotorAngle = 60.0;
+ static constexpr double kDefaultRightMotorAngle = 120.0;
+ static constexpr double kDefaultBackMotorAngle = 270.0;
+
+ /**
+ * Construct a Killough drive with the given motors and default motor angles.
+ *
+ * The default motor angles make the wheels on each corner parallel to their
+ * respective opposite sides.
+ *
+ * If a motor needs to be inverted, do so before passing it in.
+ *
+ * @param leftMotor The motor on the left corner.
+ * @param rightMotor The motor on the right corner.
+ * @param backMotor The motor on the back corner.
+ */
+ KilloughDrive(SpeedController& leftMotor, SpeedController& rightMotor,
+ SpeedController& backMotor);
+
+ /**
+ * Construct a Killough drive with the given motors.
+ *
+ * Angles are measured in degrees clockwise from the positive X axis.
+ *
+ * @param leftMotor The motor on the left corner.
+ * @param rightMotor The motor on the right corner.
+ * @param backMotor The motor on the back corner.
+ * @param leftMotorAngle The angle of the left wheel's forward direction of
+ * travel.
+ * @param rightMotorAngle The angle of the right wheel's forward direction of
+ * travel.
+ * @param backMotorAngle The angle of the back wheel's forward direction of
+ * travel.
+ */
+ KilloughDrive(SpeedController& leftMotor, SpeedController& rightMotor,
+ SpeedController& backMotor, double leftMotorAngle,
+ double rightMotorAngle, double backMotorAngle);
+
+ ~KilloughDrive() override = default;
+
+ KilloughDrive(KilloughDrive&&) = default;
+ KilloughDrive& operator=(KilloughDrive&&) = default;
+
+ /**
+ * Drive method for Killough platform.
+ *
+ * Angles are measured clockwise from the positive X axis. The robot's speed
+ * is independent from its angle or rotation rate.
+ *
+ * @param ySpeed The robot's speed along the Y axis [-1.0..1.0]. Right is
+ * positive.
+ * @param xSpeed The robot's speed along the X axis [-1.0..1.0]. Forward is
+ * positive.
+ * @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
+ * Clockwise is positive.
+ * @param gyroAngle The current angle reading from the gyro in degrees around
+ * the Z axis. Use this to implement field-oriented controls.
+ */
+ void DriveCartesian(double ySpeed, double xSpeed, double zRotation,
+ double gyroAngle = 0.0);
+
+ /**
+ * Drive method for Killough platform.
+ *
+ * Angles are measured clockwise from the positive X axis. The robot's speed
+ * is independent from its angle or rotation rate.
+ *
+ * @param magnitude The robot's speed at a given angle [-1.0..1.0]. Forward is
+ * positive.
+ * @param angle The angle around the Z axis at which the robot drives in
+ * degrees [-180..180].
+ * @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
+ * Clockwise is positive.
+ */
+ void DrivePolar(double magnitude, double angle, double zRotation);
+
+ void StopMotor() override;
+ void GetDescription(wpi::raw_ostream& desc) const override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ SpeedController& m_leftMotor;
+ SpeedController& m_rightMotor;
+ SpeedController& m_backMotor;
+
+ Vector2d m_leftVec;
+ Vector2d m_rightVec;
+ Vector2d m_backVec;
+
+ bool reported = false;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/drive/MecanumDrive.h b/wpilibc/src/main/native/include/frc/drive/MecanumDrive.h
new file mode 100644
index 0000000..e0acaca
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/drive/MecanumDrive.h
@@ -0,0 +1,146 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <wpi/raw_ostream.h>
+
+#include "frc/drive/RobotDriveBase.h"
+
+namespace frc {
+
+class SpeedController;
+
+/**
+ * A class for driving Mecanum drive platforms.
+ *
+ * Mecanum drives are rectangular with one wheel on each corner. Each wheel has
+ * rollers toed in 45 degrees toward the front or back. When looking at the
+ * wheels from the top, the roller axles should form an X across the robot.
+ *
+ * Drive base diagram:
+ * <pre>
+ * \\_______/
+ * \\ | | /
+ * | |
+ * /_|___|_\\
+ * / \\
+ * </pre>
+ *
+ * Each Drive() function provides different inverse kinematic relations for a
+ * Mecanum drive robot. Motor outputs for the right side are negated, so motor
+ * direction inversion by the user is usually unnecessary.
+ *
+ * This library uses the NED axes convention (North-East-Down as external
+ * reference in the world frame):
+ * http://www.nuclearprojects.com/ins/images/axis_big.png.
+ *
+ * The positive X axis points ahead, the positive Y axis points to the right,
+ * and the positive Z axis points down. Rotations follow the right-hand rule, so
+ * clockwise rotation around the Z axis is positive.
+ *
+ * Inputs smaller then 0.02 will be set to 0, and larger values will be scaled
+ * so that the full range is still used. This deadband value can be changed
+ * with SetDeadband().
+ *
+ * RobotDrive porting guide:
+ * <br>In MecanumDrive, the right side speed controllers are automatically
+ * inverted, while in RobotDrive, no speed controllers are automatically
+ * inverted.
+ * <br>DriveCartesian(double, double, double, double) is equivalent to
+ * RobotDrive#MecanumDrive_Cartesian(double, double, double, double)
+ * if a deadband of 0 is used, and the ySpeed and gyroAngle values are inverted
+ * compared to RobotDrive (eg DriveCartesian(xSpeed, -ySpeed, zRotation,
+ * -gyroAngle).
+ * <br>DrivePolar(double, double, double) is equivalent to
+ * RobotDrive#MecanumDrive_Polar(double, double, double) if a
+ * deadband of 0 is used.
+ */
+class MecanumDrive : public RobotDriveBase {
+ public:
+ /**
+ * Construct a MecanumDrive.
+ *
+ * If a motor needs to be inverted, do so before passing it in.
+ */
+ MecanumDrive(SpeedController& frontLeftMotor, SpeedController& rearLeftMotor,
+ SpeedController& frontRightMotor,
+ SpeedController& rearRightMotor);
+
+ ~MecanumDrive() override = default;
+
+ MecanumDrive(MecanumDrive&&) = default;
+ MecanumDrive& operator=(MecanumDrive&&) = default;
+
+ /**
+ * Drive method for Mecanum platform.
+ *
+ * Angles are measured clockwise from the positive X axis. The robot's speed
+ * is independent from its angle or rotation rate.
+ *
+ * @param ySpeed The robot's speed along the Y axis [-1.0..1.0]. Right is
+ * positive.
+ * @param xSpeed The robot's speed along the X axis [-1.0..1.0]. Forward is
+ * positive.
+ * @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
+ * Clockwise is positive.
+ * @param gyroAngle The current angle reading from the gyro in degrees around
+ * the Z axis. Use this to implement field-oriented controls.
+ */
+ void DriveCartesian(double ySpeed, double xSpeed, double zRotation,
+ double gyroAngle = 0.0);
+
+ /**
+ * Drive method for Mecanum platform.
+ *
+ * Angles are measured clockwise from the positive X axis. The robot's speed
+ * is independent from its angle or rotation rate.
+ *
+ * @param magnitude The robot's speed at a given angle [-1.0..1.0]. Forward is
+ * positive.
+ * @param angle The angle around the Z axis at which the robot drives in
+ * degrees [-180..180].
+ * @param zRotation The robot's rotation rate around the Z axis [-1.0..1.0].
+ * Clockwise is positive.
+ */
+ void DrivePolar(double magnitude, double angle, double zRotation);
+
+ /**
+ * Gets if the power sent to the right side of the drivetrain is multipled by
+ * -1.
+ *
+ * @return true if the right side is inverted
+ */
+ bool IsRightSideInverted() const;
+
+ /**
+ * Sets if the power sent to the right side of the drivetrain should be
+ * multipled by -1.
+ *
+ * @param rightSideInverted true if right side power should be multipled by -1
+ */
+ void SetRightSideInverted(bool rightSideInverted);
+
+ void StopMotor() override;
+ void GetDescription(wpi::raw_ostream& desc) const override;
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ SpeedController& m_frontLeftMotor;
+ SpeedController& m_rearLeftMotor;
+ SpeedController& m_frontRightMotor;
+ SpeedController& m_rearRightMotor;
+
+ double m_rightSideInvertMultiplier = -1.0;
+
+ bool reported = false;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/drive/RobotDriveBase.h b/wpilibc/src/main/native/include/frc/drive/RobotDriveBase.h
new file mode 100644
index 0000000..206434e
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/drive/RobotDriveBase.h
@@ -0,0 +1,102 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <wpi/ArrayRef.h>
+#include <wpi/raw_ostream.h>
+
+#include "frc/MotorSafety.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class SpeedController;
+
+/**
+ * Common base class for drive platforms.
+ */
+class RobotDriveBase : public MotorSafety, public SendableBase {
+ public:
+ /**
+ * The location of a motor on the robot for the purpose of driving.
+ */
+ enum MotorType {
+ kFrontLeft = 0,
+ kFrontRight = 1,
+ kRearLeft = 2,
+ kRearRight = 3,
+ kLeft = 0,
+ kRight = 1,
+ kBack = 2
+ };
+
+ RobotDriveBase();
+ ~RobotDriveBase() override = default;
+
+ RobotDriveBase(RobotDriveBase&&) = default;
+ RobotDriveBase& operator=(RobotDriveBase&&) = default;
+
+ /**
+ * Sets the deadband applied to the drive inputs (e.g., joystick values).
+ *
+ * The default value is 0.02. Inputs smaller than the deadband are set to 0.0
+ * while inputs larger than the deadband are scaled from 0.0 to 1.0. See
+ * ApplyDeadband().
+ *
+ * @param deadband The deadband to set.
+ */
+ void SetDeadband(double deadband);
+
+ /**
+ * Configure the scaling factor for using RobotDrive with motor controllers in
+ * a mode other than PercentVbus or to limit the maximum output.
+ *
+ * @param maxOutput Multiplied with the output percentage computed by the
+ * drive functions.
+ */
+ void SetMaxOutput(double maxOutput);
+
+ /**
+ * Feed the motor safety object. Resets the timer that will stop the motors if
+ * it completes.
+ *
+ * @see MotorSafetyHelper::Feed()
+ */
+ void FeedWatchdog();
+
+ void StopMotor() override = 0;
+ void GetDescription(wpi::raw_ostream& desc) const override = 0;
+
+ protected:
+ /**
+ * Limit motor values to the -1.0 to +1.0 range.
+ */
+ double Limit(double number);
+
+ /**
+ * Returns 0.0 if the given value is within the specified range around zero.
+ * The remaining range between the deadband and 1.0 is scaled from 0.0 to 1.0.
+ *
+ * @param value value to clip
+ * @param deadband range around zero
+ */
+ double ApplyDeadband(double number, double deadband);
+
+ /**
+ * Normalize all wheel speeds if the magnitude of any wheel is greater than
+ * 1.0.
+ */
+ void Normalize(wpi::MutableArrayRef<double> wheelSpeeds);
+
+ double m_deadband = 0.02;
+ double m_maxOutput = 1.0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/drive/Vector2d.h b/wpilibc/src/main/native/include/frc/drive/Vector2d.h
new file mode 100644
index 0000000..c9bd08a
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/drive/Vector2d.h
@@ -0,0 +1,49 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+/**
+ * This is a 2D vector struct that supports basic vector operations.
+ */
+struct Vector2d {
+ Vector2d() = default;
+ Vector2d(double x, double y);
+
+ /**
+ * Rotate a vector in Cartesian space.
+ *
+ * @param angle angle in degrees by which to rotate vector counter-clockwise.
+ */
+ void Rotate(double angle);
+
+ /**
+ * Returns dot product of this vector with argument.
+ *
+ * @param vec Vector with which to perform dot product.
+ */
+ double Dot(const Vector2d& vec) const;
+
+ /**
+ * Returns magnitude of vector.
+ */
+ double Magnitude() const;
+
+ /**
+ * Returns scalar projection of this vector onto argument.
+ *
+ * @param vec Vector onto which to project this vector.
+ */
+ double ScalarProject(const Vector2d& vec) const;
+
+ double x = 0.0;
+ double y = 0.0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/filters/Filter.h b/wpilibc/src/main/native/include/frc/filters/Filter.h
new file mode 100644
index 0000000..b0c0c11
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/filters/Filter.h
@@ -0,0 +1,58 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include "frc/PIDSource.h"
+
+namespace frc {
+
+/**
+ * Interface for filters
+ */
+class Filter : public PIDSource {
+ public:
+ explicit Filter(PIDSource& source);
+ explicit Filter(std::shared_ptr<PIDSource> source);
+ virtual ~Filter() = default;
+
+ Filter(Filter&&) = default;
+ Filter& operator=(Filter&&) = default;
+
+ // PIDSource interface
+ void SetPIDSourceType(PIDSourceType pidSource) override;
+ PIDSourceType GetPIDSourceType() const override;
+ double PIDGet() override = 0;
+
+ /**
+ * Returns the current filter estimate without also inserting new data as
+ * PIDGet() would do.
+ *
+ * @return The current filter estimate
+ */
+ virtual double Get() const = 0;
+
+ /**
+ * Reset the filter state
+ */
+ virtual void Reset() = 0;
+
+ protected:
+ /**
+ * Calls PIDGet() of source
+ *
+ * @return Current value of source
+ */
+ double PIDGetSource();
+
+ private:
+ std::shared_ptr<PIDSource> m_source;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/filters/LinearDigitalFilter.h b/wpilibc/src/main/native/include/frc/filters/LinearDigitalFilter.h
new file mode 100644
index 0000000..472d53b
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/filters/LinearDigitalFilter.h
@@ -0,0 +1,197 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include <wpi/ArrayRef.h>
+
+#include "frc/circular_buffer.h"
+#include "frc/filters/Filter.h"
+
+namespace frc {
+
+/**
+ * This class implements a linear, digital filter. All types of FIR and IIR
+ * filters are supported. Static factory methods are provided to create commonly
+ * used types of filters.
+ *
+ * Filters are of the form:<br>
+ * y[n] = (b0 * x[n] + b1 * x[n-1] + ... + bP * x[n-P]) -
+ * (a0 * y[n-1] + a2 * y[n-2] + ... + aQ * y[n-Q])
+ *
+ * Where:<br>
+ * y[n] is the output at time "n"<br>
+ * x[n] is the input at time "n"<br>
+ * y[n-1] is the output from the LAST time step ("n-1")<br>
+ * x[n-1] is the input from the LAST time step ("n-1")<br>
+ * b0...bP are the "feedforward" (FIR) gains<br>
+ * a0...aQ are the "feedback" (IIR) gains<br>
+ * IMPORTANT! Note the "-" sign in front of the feedback term! This is a common
+ * convention in signal processing.
+ *
+ * What can linear filters do? Basically, they can filter, or diminish, the
+ * effects of undesirable input frequencies. High frequencies, or rapid changes,
+ * can be indicative of sensor noise or be otherwise undesirable. A "low pass"
+ * filter smooths out the signal, reducing the impact of these high frequency
+ * components. Likewise, a "high pass" filter gets rid of slow-moving signal
+ * components, letting you detect large changes more easily.
+ *
+ * Example FRC applications of filters:
+ * - Getting rid of noise from an analog sensor input (note: the roboRIO's FPGA
+ * can do this faster in hardware)
+ * - Smoothing out joystick input to prevent the wheels from slipping or the
+ * robot from tipping
+ * - Smoothing motor commands so that unnecessary strain isn't put on
+ * electrical or mechanical components
+ * - If you use clever gains, you can make a PID controller out of this class!
+ *
+ * For more on filters, I highly recommend the following articles:<br>
+ * http://en.wikipedia.org/wiki/Linear_filter<br>
+ * http://en.wikipedia.org/wiki/Iir_filter<br>
+ * http://en.wikipedia.org/wiki/Fir_filter<br>
+ *
+ * Note 1: PIDGet() should be called by the user on a known, regular period.
+ * You can set up a Notifier to do this (look at the WPILib PIDController
+ * class), or do it "inline" with code in a periodic function.
+ *
+ * Note 2: For ALL filters, gains are necessarily a function of frequency. If
+ * you make a filter that works well for you at, say, 100Hz, you will most
+ * definitely need to adjust the gains if you then want to run it at 200Hz!
+ * Combining this with Note 1 - the impetus is on YOU as a developer to make
+ * sure PIDGet() gets called at the desired, constant frequency!
+ */
+class LinearDigitalFilter : public Filter {
+ public:
+ /**
+ * Create a linear FIR or IIR filter.
+ *
+ * @param source The PIDSource object that is used to get values
+ * @param ffGains The "feed forward" or FIR gains
+ * @param fbGains The "feed back" or IIR gains
+ */
+ LinearDigitalFilter(PIDSource& source, wpi::ArrayRef<double> ffGains,
+ wpi::ArrayRef<double> fbGains);
+
+ /**
+ * Create a linear FIR or IIR filter.
+ *
+ * @param source The PIDSource object that is used to get values
+ * @param ffGains The "feed forward" or FIR gains
+ * @param fbGains The "feed back" or IIR gains
+ */
+ LinearDigitalFilter(std::shared_ptr<PIDSource> source,
+ wpi::ArrayRef<double> ffGains,
+ wpi::ArrayRef<double> fbGains);
+
+ LinearDigitalFilter(LinearDigitalFilter&&) = default;
+ LinearDigitalFilter& operator=(LinearDigitalFilter&&) = default;
+
+ // Static methods to create commonly used filters
+ /**
+ * Creates a one-pole IIR low-pass filter of the form:<br>
+ * y[n] = (1 - gain) * x[n] + gain * y[n-1]<br>
+ * where gain = e<sup>-dt / T</sup>, T is the time constant in seconds
+ *
+ * This filter is stable for time constants greater than zero.
+ *
+ * @param source The PIDSource object that is used to get values
+ * @param timeConstant The discrete-time time constant in seconds
+ * @param period The period in seconds between samples taken by the user
+ */
+ static LinearDigitalFilter SinglePoleIIR(PIDSource& source,
+ double timeConstant, double period);
+
+ /**
+ * Creates a first-order high-pass filter of the form:<br>
+ * y[n] = gain * x[n] + (-gain) * x[n-1] + gain * y[n-1]<br>
+ * where gain = e<sup>-dt / T</sup>, T is the time constant in seconds
+ *
+ * This filter is stable for time constants greater than zero.
+ *
+ * @param source The PIDSource object that is used to get values
+ * @param timeConstant The discrete-time time constant in seconds
+ * @param period The period in seconds between samples taken by the user
+ */
+ static LinearDigitalFilter HighPass(PIDSource& source, double timeConstant,
+ double period);
+
+ /**
+ * Creates a K-tap FIR moving average filter of the form:<br>
+ * y[n] = 1/k * (x[k] + x[k-1] + … + x[0])
+ *
+ * This filter is always stable.
+ *
+ * @param source The PIDSource object that is used to get values
+ * @param taps The number of samples to average over. Higher = smoother but
+ * slower
+ */
+ static LinearDigitalFilter MovingAverage(PIDSource& source, int taps);
+
+ /**
+ * Creates a one-pole IIR low-pass filter of the form:<br>
+ * y[n] = (1 - gain) * x[n] + gain * y[n-1]<br>
+ * where gain = e<sup>-dt / T</sup>, T is the time constant in seconds
+ *
+ * This filter is stable for time constants greater than zero.
+ *
+ * @param source The PIDSource object that is used to get values
+ * @param timeConstant The discrete-time time constant in seconds
+ * @param period The period in seconds between samples taken by the user
+ */
+ static LinearDigitalFilter SinglePoleIIR(std::shared_ptr<PIDSource> source,
+ double timeConstant, double period);
+
+ /**
+ * Creates a first-order high-pass filter of the form:<br>
+ * y[n] = gain * x[n] + (-gain) * x[n-1] + gain * y[n-1]<br>
+ * where gain = e<sup>-dt / T</sup>, T is the time constant in seconds
+ *
+ * This filter is stable for time constants greater than zero.
+ *
+ * @param source The PIDSource object that is used to get values
+ * @param timeConstant The discrete-time time constant in seconds
+ * @param period The period in seconds between samples taken by the user
+ */
+ static LinearDigitalFilter HighPass(std::shared_ptr<PIDSource> source,
+ double timeConstant, double period);
+
+ /**
+ * Creates a K-tap FIR moving average filter of the form:<br>
+ * y[n] = 1/k * (x[k] + x[k-1] + … + x[0])
+ *
+ * This filter is always stable.
+ *
+ * @param source The PIDSource object that is used to get values
+ * @param taps The number of samples to average over. Higher = smoother but
+ * slower
+ */
+ static LinearDigitalFilter MovingAverage(std::shared_ptr<PIDSource> source,
+ int taps);
+
+ // Filter interface
+ double Get() const override;
+ void Reset() override;
+
+ // PIDSource interface
+ /**
+ * Calculates the next value of the filter
+ *
+ * @return The filtered value at this step
+ */
+ double PIDGet() override;
+
+ private:
+ circular_buffer<double> m_inputs;
+ circular_buffer<double> m_outputs;
+ std::vector<double> m_inputGains;
+ std::vector<double> m_outputGains;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/interfaces/Accelerometer.h b/wpilibc/src/main/native/include/frc/interfaces/Accelerometer.h
new file mode 100644
index 0000000..499ba5b
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/interfaces/Accelerometer.h
@@ -0,0 +1,56 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+/**
+ * Interface for 3-axis accelerometers.
+ */
+class Accelerometer {
+ public:
+ Accelerometer() = default;
+ virtual ~Accelerometer() = default;
+
+ Accelerometer(Accelerometer&&) = default;
+ Accelerometer& operator=(Accelerometer&&) = default;
+
+ enum Range { kRange_2G = 0, kRange_4G = 1, kRange_8G = 2, kRange_16G = 3 };
+
+ /**
+ * Common interface for setting the measuring range of an accelerometer.
+ *
+ * @param range The maximum acceleration, positive or negative, that the
+ * accelerometer will measure. Not all accelerometers support all
+ * ranges.
+ */
+ virtual void SetRange(Range range) = 0;
+
+ /**
+ * Common interface for getting the x axis acceleration.
+ *
+ * @return The acceleration along the x axis in g-forces
+ */
+ virtual double GetX() = 0;
+
+ /**
+ * Common interface for getting the y axis acceleration.
+ *
+ * @return The acceleration along the y axis in g-forces
+ */
+ virtual double GetY() = 0;
+
+ /**
+ * Common interface for getting the z axis acceleration.
+ *
+ * @return The acceleration along the z axis in g-forces
+ */
+ virtual double GetZ() = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/interfaces/Gyro.h b/wpilibc/src/main/native/include/frc/interfaces/Gyro.h
new file mode 100644
index 0000000..b5aa332
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/interfaces/Gyro.h
@@ -0,0 +1,72 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+/**
+ * Interface for yaw rate gyros.
+ */
+class Gyro {
+ public:
+ Gyro() = default;
+ virtual ~Gyro() = default;
+
+ Gyro(Gyro&&) = default;
+ Gyro& operator=(Gyro&&) = default;
+
+ /**
+ * Calibrate the gyro by running for a number of samples and computing the
+ * center value. Then use the center value as the Accumulator center value for
+ * subsequent measurements. It's important to make sure that the robot is not
+ * moving while the centering calculations are in progress, this is typically
+ * done when the robot is first turned on while it's sitting at rest before
+ * the competition starts.
+ */
+ virtual void Calibrate() = 0;
+
+ /**
+ * Reset the gyro. Resets the gyro to a heading of zero. This can be used if
+ * there is significant drift in the gyro and it needs to be recalibrated
+ * after it has been running.
+ */
+ virtual void Reset() = 0;
+
+ /**
+ * Return the actual angle in degrees that the robot is currently facing.
+ *
+ * The angle is based on the current accumulator value corrected by the
+ * oversampling rate, the gyro type and the A/D calibration values. The angle
+ * is continuous, that is it will continue from 360 to 361 degrees. This
+ * allows algorithms that wouldn't want to see a discontinuity in the gyro
+ * output as it sweeps past from 360 to 0 on the second time around.
+ *
+ * The angle is expected to increase as the gyro turns clockwise when looked
+ * at from the top. It needs to follow NED axis conventions in order to work
+ * properly with dependent control loops.
+ *
+ * @return the current heading of the robot in degrees. This heading is based
+ * on integration of the returned rate from the gyro.
+ */
+ virtual double GetAngle() const = 0;
+
+ /**
+ * Return the rate of rotation of the gyro.
+ *
+ * The rate is based on the most recent reading of the gyro analog value.
+ *
+ * The rate is expected to be positive as the gyro turns clockwise when looked
+ * at from the top. It needs to follow NED axis conventions in order to work
+ * properly with dependent control loops.
+ *
+ * @return the current rate in degrees per second
+ */
+ virtual double GetRate() const = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/interfaces/Potentiometer.h b/wpilibc/src/main/native/include/frc/interfaces/Potentiometer.h
new file mode 100644
index 0000000..219e6ba
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/interfaces/Potentiometer.h
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/PIDSource.h"
+
+namespace frc {
+
+/**
+ * Interface for potentiometers.
+ */
+class Potentiometer : public PIDSource {
+ public:
+ Potentiometer() = default;
+ virtual ~Potentiometer() = default;
+
+ Potentiometer(Potentiometer&&) = default;
+ Potentiometer& operator=(Potentiometer&&) = default;
+
+ /**
+ * Common interface for getting the current value of a potentiometer.
+ *
+ * @return The current set speed. Value is between -1.0 and 1.0.
+ */
+ virtual double Get() const = 0;
+
+ void SetPIDSourceType(PIDSourceType pidSource) override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/livewindow/LiveWindow.h b/wpilibc/src/main/native/include/frc/livewindow/LiveWindow.h
new file mode 100644
index 0000000..465a4bb
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/livewindow/LiveWindow.h
@@ -0,0 +1,218 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2012-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <wpi/Twine.h>
+#include <wpi/deprecated.h>
+
+#include "frc/smartdashboard/Sendable.h"
+
+namespace frc {
+
+/**
+ * The LiveWindow class is the public interface for putting sensors and
+ * actuators on the LiveWindow.
+ */
+class LiveWindow {
+ public:
+ LiveWindow(const LiveWindow&) = delete;
+ LiveWindow& operator=(const LiveWindow&) = delete;
+
+ /**
+ * Get an instance of the LiveWindow main class.
+ *
+ * This is a singleton to guarantee that there is only a single instance
+ * regardless of how many times GetInstance is called.
+ */
+ static LiveWindow* GetInstance();
+
+ WPI_DEPRECATED("no longer required")
+ void Run();
+
+ /**
+ * Add a Sensor associated with the subsystem and call it by the given name.
+ *
+ * @param subsystem The subsystem this component is part of.
+ * @param name The name of this component.
+ * @param component A Sendable component that represents a sensor.
+ */
+ WPI_DEPRECATED("use Sendable::SetName() instead")
+ void AddSensor(const wpi::Twine& subsystem, const wpi::Twine& name,
+ Sendable* component);
+
+ /**
+ * Add a Sensor associated with the subsystem and call it by the given name.
+ *
+ * @param subsystem The subsystem this component is part of.
+ * @param name The name of this component.
+ * @param component A Sendable component that represents a sensor.
+ */
+ WPI_DEPRECATED("use Sendable::SetName() instead")
+ void AddSensor(const wpi::Twine& subsystem, const wpi::Twine& name,
+ Sendable& component);
+
+ /**
+ * Add a Sensor associated with the subsystem and call it by the given name.
+ *
+ * @param subsystem The subsystem this component is part of.
+ * @param name The name of this component.
+ * @param component A Sendable component that represents a sensor.
+ */
+ WPI_DEPRECATED("use Sendable::SetName() instead")
+ void AddSensor(const wpi::Twine& subsystem, const wpi::Twine& name,
+ std::shared_ptr<Sendable> component);
+
+ /**
+ * Add an Actuator associated with the subsystem and call it by the given
+ * name.
+ *
+ * @param subsystem The subsystem this component is part of.
+ * @param name The name of this component.
+ * @param component A Sendable component that represents a actuator.
+ */
+ WPI_DEPRECATED("use Sendable::SetName() instead")
+ void AddActuator(const wpi::Twine& subsystem, const wpi::Twine& name,
+ Sendable* component);
+
+ /**
+ * Add an Actuator associated with the subsystem and call it by the given
+ * name.
+ *
+ * @param subsystem The subsystem this component is part of.
+ * @param name The name of this component.
+ * @param component A Sendable component that represents a actuator.
+ */
+ WPI_DEPRECATED("use Sendable::SetName() instead")
+ void AddActuator(const wpi::Twine& subsystem, const wpi::Twine& name,
+ Sendable& component);
+
+ /**
+ * Add an Actuator associated with the subsystem and call it by the given
+ * name.
+ *
+ * @param subsystem The subsystem this component is part of.
+ * @param name The name of this component.
+ * @param component A Sendable component that represents a actuator.
+ */
+ WPI_DEPRECATED("use Sendable::SetName() instead")
+ void AddActuator(const wpi::Twine& subsystem, const wpi::Twine& name,
+ std::shared_ptr<Sendable> component);
+
+ /**
+ * Meant for internal use in other WPILib classes.
+ *
+ * @deprecated Use SendableBase::SetName() instead.
+ */
+ WPI_DEPRECATED("use SensorUtil::SetName() instead")
+ void AddSensor(const wpi::Twine& type, int channel, Sendable* component);
+
+ /**
+ * Meant for internal use in other WPILib classes.
+ *
+ * @deprecated Use SendableBase::SetName() instead.
+ */
+ WPI_DEPRECATED("use SensorUtil::SetName() instead")
+ void AddActuator(const wpi::Twine& type, int channel, Sendable* component);
+
+ /**
+ * Meant for internal use in other WPILib classes.
+ *
+ * @deprecated Use SendableBase::SetName() instead.
+ */
+ WPI_DEPRECATED("use SensorUtil::SetName() instead")
+ void AddActuator(const wpi::Twine& type, int module, int channel,
+ Sendable* component);
+
+ /**
+ * Add a component to the LiveWindow.
+ *
+ * @param sendable component to add
+ */
+ void Add(std::shared_ptr<Sendable> component);
+
+ /**
+ * Add a component to the LiveWindow.
+ *
+ * @param sendable component to add
+ */
+ void Add(Sendable* component);
+
+ /**
+ * Add a child component to a component.
+ *
+ * @param parent parent component
+ * @param child child component
+ */
+ void AddChild(Sendable* parent, std::shared_ptr<Sendable> component);
+
+ /**
+ * Add a child component to a component.
+ *
+ * @param parent parent component
+ * @param child child component
+ */
+ void AddChild(Sendable* parent, void* component);
+
+ /**
+ * Remove the component from the LiveWindow.
+ *
+ * @param sendable component to remove
+ */
+ void Remove(Sendable* component);
+
+ /**
+ * Enable telemetry for a single component.
+ *
+ * @param sendable component
+ */
+ void EnableTelemetry(Sendable* component);
+
+ /**
+ * Disable telemetry for a single component.
+ *
+ * @param sendable component
+ */
+ void DisableTelemetry(Sendable* component);
+
+ /**
+ * Disable ALL telemetry.
+ */
+ void DisableAllTelemetry();
+
+ bool IsEnabled() const;
+
+ /**
+ * Change the enabled status of LiveWindow.
+ *
+ * If it changes to enabled, start livewindow running otherwise stop it
+ */
+ void SetEnabled(bool enabled);
+
+ /**
+ * Tell all the sensors to update (send) their values.
+ *
+ * Actuators are handled through callbacks on their value changing from the
+ * SmartDashboard widgets.
+ */
+ void UpdateValues();
+
+ private:
+ LiveWindow();
+
+ struct Impl;
+ std::unique_ptr<Impl> m_impl;
+
+ /**
+ * Updates the entries, without using a mutex or lock.
+ */
+ void UpdateValuesUnsafe();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/livewindow/LiveWindowSendable.h b/wpilibc/src/main/native/include/frc/livewindow/LiveWindowSendable.h
new file mode 100644
index 0000000..172e0cb
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/livewindow/LiveWindowSendable.h
@@ -0,0 +1,52 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2012-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <string>
+
+#include <wpi/deprecated.h>
+
+#include "frc/smartdashboard/Sendable.h"
+
+namespace frc {
+
+/**
+ * Live Window Sendable is a special type of object sendable to the live window.
+ * @deprecated Use Sendable directly instead
+ */
+class LiveWindowSendable : public Sendable {
+ public:
+ WPI_DEPRECATED("use Sendable directly instead")
+ LiveWindowSendable() = default;
+ LiveWindowSendable(LiveWindowSendable&&) = default;
+ LiveWindowSendable& operator=(LiveWindowSendable&&) = default;
+
+ /**
+ * Update the table for this sendable object with the latest values.
+ */
+ virtual void UpdateTable() = 0;
+
+ /**
+ * Start having this sendable object automatically respond to value changes
+ * reflect the value on the table.
+ */
+ virtual void StartLiveWindowMode() = 0;
+
+ /**
+ * Stop having this sendable object automatically respond to value changes.
+ */
+ virtual void StopLiveWindowMode() = 0;
+
+ std::string GetName() const override;
+ void SetName(const wpi::Twine& name) override;
+ std::string GetSubsystem() const override;
+ void SetSubsystem(const wpi::Twine& subsystem) override;
+ void InitSendable(SendableBuilder& builder) override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInLayouts.h b/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInLayouts.h
new file mode 100644
index 0000000..6a61b87
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInLayouts.h
@@ -0,0 +1,53 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/shuffleboard/LayoutType.h"
+
+namespace frc {
+
+/**
+ * The types of layouts bundled with Shuffleboard.
+ *
+ * <pre>{@code
+ * ShuffleboardLayout myList = Shuffleboard::GetTab("My Tab")
+ * .GetLayout(BuiltinLayouts::kList, "My List");
+ * }</pre>
+ */
+class BuiltInLayouts {
+ public:
+ /**
+ * Groups components in a vertical list. New widgets added to the layout will
+ * be placed at the bottom of the list. <br>Custom properties: <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Label position</td><td>String</td><td>"BOTTOM"</td>
+ * <td>The position of component labels inside the grid. One of
+ * {@code ["TOP", "LEFT", "BOTTOM", "RIGHT", "HIDDEN"}</td></tr>
+ * </table>
+ */
+ static const LayoutType kList;
+
+ /**
+ * Groups components in an <i>n</i> x <i>m</i> grid. Grid layouts default to
+ * 3x3. <br>Custom properties: <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Number of columns</td><td>Number</td><td>3</td><td>Must be in the
+ * range [1,15]</td>
+ * </tr>
+ * <tr><td>Number of rows</td><td>Number</td><td>3</td><td>Must be in the
+ * range [1,15]</td></tr> <tr> <td>Label position</td> <td>String</td>
+ * <td>"BOTTOM"</td>
+ * <td>The position of component labels inside the grid.
+ * One of {@code ["TOP", "LEFT", "BOTTOM", "RIGHT", "HIDDEN"}</td>
+ * </tr>
+ * </table>
+ */
+ static const LayoutType kGrid;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInWidgets.h b/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInWidgets.h
new file mode 100644
index 0000000..1fd720f
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInWidgets.h
@@ -0,0 +1,387 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/shuffleboard/WidgetType.h"
+
+namespace frc {
+
+/**
+ * The types of the widgets bundled with Shuffleboard.
+ *
+ * <p>For example, setting a number to be displayed with a slider:
+ * <pre>{@code
+ * NetworkTableEntry example = Shuffleboard.getTab("My Tab")
+ * .add("My Number", 0)
+ * .withWidget(BuiltInWidgets.kNumberSlider)
+ * .getEntry();
+ * }</pre>
+ *
+ * <p>Each value in this enum goes into detail on what data types that widget
+ * can support, as well as the custom properties that widget uses.
+ */
+class BuiltInWidgets {
+ public:
+ /**
+ * Displays a value with a simple text field.
+ * <br>Supported types:
+ * <ul>
+ * <li>String</li>
+ * <li>Number</li>
+ * <li>Boolean</li>
+ * </ul>
+ * <br>This widget has no custom properties.
+ */
+ static const WidgetType kTextView;
+ /**
+ * Displays a number with a controllable slider.
+ * <br>Supported types:
+ * <ul>
+ * <li>Number</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Min</td><td>Number</td><td>-1.0</td><td>The minimum value of the
+ * slider</td></tr> <tr><td>Max</td><td>Number</td><td>1.0</td><td>The maximum
+ * value of the slider</td></tr> <tr><td>Block
+ * increment</td><td>Number</td><td>0.0625</td> <td>How much to move the
+ * slider by with the arrow keys</td></tr>
+ * </table>
+ */
+ static const WidgetType kNumberSlider;
+ /**
+ * Displays a number with a view-only bar.
+ * <br>Supported types:
+ * <ul>
+ * <li>Number</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Min</td><td>Number</td><td>-1.0</td><td>The minimum value of the
+ * bar</td></tr> <tr><td>Max</td><td>Number</td><td>1.0</td><td>The maximum
+ * value of the bar</td></tr>
+ * <tr><td>Center</td><td>Number</td><td>0</td><td>The center ("zero") value
+ * of the bar</td></tr>
+ * </table>
+ */
+ static const WidgetType kNumberBar;
+ /**
+ * Displays a number with a view-only dial. Displayed values are rounded to
+ * the nearest integer. <br>Supported types: <ul> <li>Number</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Min</td><td>Number</td><td>0</td><td>The minimum value of the
+ * dial</td></tr> <tr><td>Max</td><td>Number</td><td>100</td><td>The maximum
+ * value of the dial</td></tr> <tr><td>Show
+ * value</td><td>Boolean</td><td>true</td> <td>Whether or not to show the
+ * value as text</td></tr>
+ * </table>
+ */
+ static const WidgetType kDial;
+ /**
+ * Displays a number with a graph. <strong>NOTE:</strong> graphs can be taxing
+ * on the computer running the dashboard. Keep the number of visible data
+ * points to a minimum. Making the widget smaller also helps with performance,
+ * but may cause the graph to become difficult to read. <br>Supported types:
+ * <ul>
+ * <li>Number</li>
+ * <li>Number array</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Visible time</td><td>Number</td><td>30</td>
+ * <td>How long, in seconds, should past data be visible for</td></tr>
+ * </table>
+ */
+ static const WidgetType kGraph;
+ /**
+ * Displays a boolean value as a large colored box.
+ * <br>Supported types:
+ * <ul>
+ * <li>Boolean</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Color when true</td><td>Color</td><td>"green"</td>
+ * <td>Can be specified as a string ({@code "#00FF00"}) or a rgba integer
+ * ({@code 0x00FF0000})
+ * </td></tr>
+ * <tr><td>Color when false</td><td>Color</td><td>"red"</td>
+ * <td>Can be specified as a string or a number</td></tr>
+ * </table>
+ */
+ static const WidgetType kBooleanBox;
+ /**
+ * Displays a boolean with a large interactive toggle button.
+ * <br>Supported types:
+ * <ul>
+ * <li>Boolean</li>
+ * </ul>
+ * <br>This widget has no custom properties.
+ */
+ static const WidgetType kToggleButton;
+ /**
+ * Displays a boolean with a fixed-size toggle switch.
+ * <br>Supported types:
+ * <ul>
+ * <li>Boolean</li>
+ * </ul>
+ * <br>This widget has no custom properties.
+ */
+ static const WidgetType kToggleSwitch;
+ /**
+ * Displays an analog input or a raw number with a number bar.
+ * <br>Supported types:
+ * <ul>
+ * <li>Number</li>
+ * <li>{@link edu.wpi.first.wpilibj.AnalogInput}</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Min</td><td>Number</td><td>0</td><td>The minimum value of the
+ * bar</td></tr> <tr><td>Max</td><td>Number</td><td>5</td><td>The maximum
+ * value of the bar</td></tr>
+ * <tr><td>Center</td><td>Number</td><td>0</td><td>The center ("zero") value
+ * of the bar</td></tr>
+ * <tr><td>Orientation</td><td>String</td><td>"HORIZONTAL"</td>
+ * <td>The orientation of the bar. One of {@code ["HORIZONTAL",
+ * "VERTICAL"]}</td></tr> <tr><td>Number of tick
+ * marks</td><td>Number</td><td>5</td> <td>The number of discrete ticks on the
+ * bar</td></tr>
+ * </table>
+ */
+ static const WidgetType kVoltageView;
+ /**
+ * Displays a {@link edu.wpi.first.wpilibj.PowerDistributionPanel
+ * PowerDistributionPanel}. <br>Supported types: <ul> <li>{@link
+ * edu.wpi.first.wpilibj.PowerDistributionPanel}</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Show voltage and current values</td><td>Boolean</td><td>true</td>
+ * <td>Whether or not to display the voltage and current draw</td></tr>
+ * </table>
+ */
+ static const WidgetType kPowerDistributionPanel;
+ /**
+ * Displays a {@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser
+ * SendableChooser} with a dropdown combo box with a list of options.
+ * <br>Supported types:
+ * <ul>
+ * <li>{@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser}</li>
+ * </ul>
+ * <br>This widget has no custom properties.
+ */
+ static const WidgetType kComboBoxChooser;
+ /**
+ * Displays a {@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser
+ * SendableChooser} with a toggle button for each available option.
+ * <br>Supported types:
+ * <ul>
+ * <li>{@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser}</li>
+ * </ul>
+ * <br>This widget has no custom properties.
+ */
+ static const WidgetType kSplitButtonChooser;
+ /**
+ * Displays an {@link edu.wpi.first.wpilibj.Encoder} displaying its speed,
+ * total travelled distance, and its distance per tick. <br>Supported types:
+ * <ul>
+ * <li>{@link edu.wpi.first.wpilibj.Encoder}</li>
+ * </ul>
+ * <br>This widget has no custom properties.
+ */
+ static const WidgetType kEncoder;
+ /**
+ * Displays a {@link edu.wpi.first.wpilibj.SpeedController SpeedController}.
+ * The speed controller will be controllable from the dashboard when test mode
+ * is enabled, but will otherwise be view-only. <br>Supported types: <ul>
+ * <li>{@link edu.wpi.first.wpilibj.PWMSpeedController}</li>
+ * <li>{@link edu.wpi.first.wpilibj.DMC60}</li>
+ * <li>{@link edu.wpi.first.wpilibj.Jaguar}</li>
+ * <li>{@link edu.wpi.first.wpilibj.PWMTalonSRX}</li>
+ * <li>{@link edu.wpi.first.wpilibj.PWMVictorSPX}</li>
+ * <li>{@link edu.wpi.first.wpilibj.SD540}</li>
+ * <li>{@link edu.wpi.first.wpilibj.Spark}</li>
+ * <li>{@link edu.wpi.first.wpilibj.Talon}</li>
+ * <li>{@link edu.wpi.first.wpilibj.Victor}</li>
+ * <li>{@link edu.wpi.first.wpilibj.VictorSP}</li>
+ * <li>{@link edu.wpi.first.wpilibj.SpeedControllerGroup}</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Orientation</td><td>String</td><td>"HORIZONTAL"</td>
+ * <td>One of {@code ["HORIZONTAL", "VERTICAL"]}</td></tr>
+ * </table>
+ */
+ static const WidgetType kSpeedController;
+ /**
+ * Displays a command with a toggle button. Pressing the button will start the
+ * command, and the button will automatically release when the command
+ * completes. <br>Supported types: <ul> <li>{@link
+ * edu.wpi.first.wpilibj.command.Command}</li> <li>{@link
+ * edu.wpi.first.wpilibj.command.CommandGroup}</li> <li>Any custom subclass of
+ * {@code Command} or {@code CommandGroup}</li>
+ * </ul>
+ * <br>This widget has no custom properties.
+ */
+ static const WidgetType kCommand;
+ /**
+ * Displays a PID command with a checkbox and an editor for the PIDF
+ * constants. Selecting the checkbox will start the command, and the checkbox
+ * will automatically deselect when the command completes. <br>Supported
+ * types: <ul> <li>{@link edu.wpi.first.wpilibj.command.PIDCommand}</li>
+ * <li>Any custom subclass of {@code PIDCommand}</li>
+ * </ul>
+ * <br>This widget has no custom properties.
+ */
+ static const WidgetType kPIDCommand;
+ /**
+ * Displays a PID controller with an editor for the PIDF constants and a
+ * toggle switch for enabling and disabling the controller. <br>Supported
+ * types: <ul> <li>{@link edu.wpi.first.wpilibj.PIDController}</li>
+ * </ul>
+ * <br>This widget has no custom properties.
+ */
+ static const WidgetType kPIDController;
+ /**
+ * Displays an accelerometer with a number bar displaying the magnitude of the
+ * acceleration and text displaying the exact value. <br>Supported types: <ul>
+ * <li>{@link edu.wpi.first.wpilibj.AnalogAccelerometer}</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Min</td><td>Number</td><td>-1</td>
+ * <td>The minimum acceleration value to display</td></tr>
+ * <tr><td>Max</td><td>Number</td><td>1</td>
+ * <td>The maximum acceleration value to display</td></tr>
+ * <tr><td>Show text</td><td>Boolean</td><td>true</td>
+ * <td>Show or hide the acceleration values</td></tr>
+ * <tr><td>Precision</td><td>Number</td><td>2</td>
+ * <td>How many numbers to display after the decimal point</td></tr>
+ * <tr><td>Show tick marks</td><td>Boolean</td><td>false</td>
+ * <td>Show or hide the tick marks on the number bars</td></tr>
+ * </table>
+ */
+ static const WidgetType kAccelerometer;
+ /**
+ * Displays a 3-axis accelerometer with a number bar for each axis'
+ * accleration. <br>Supported types: <ul> <li>{@link
+ * edu.wpi.first.wpilibj.ADXL345_I2C}</li> <li>{@link
+ * edu.wpi.first.wpilibj.ADXL345_SPI}</li> <li>{@link
+ * edu.wpi.first.wpilibj.ADXL362}</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Range</td><td>{@link Range}</td><td>k16G</td><td>The accelerometer
+ * range</td></tr> <tr><td>Show value</td><td>Boolean</td><td>true</td>
+ * <td>Show or hide the acceleration values</td></tr>
+ * <tr><td>Precision</td><td>Number</td><td>2</td>
+ * <td>How many numbers to display after the decimal point</td></tr>
+ * <tr><td>Show tick marks</td><td>Boolean</td><td>false</td>
+ * <td>Show or hide the tick marks on the number bars</td></tr>
+ * </table>
+ */
+ static const WidgetType k3AxisAccelerometer;
+ /**
+ * Displays a gyro with a dial from 0 to 360 degrees.
+ * <br>Supported types:
+ * <ul>
+ * <li>{@link edu.wpi.first.wpilibj.ADXRS450_Gyro}</li>
+ * <li>{@link edu.wpi.first.wpilibj.AnalogGyro}</li>
+ * <li>Any custom subclass of {@code GyroBase} (such as a MXP gyro)</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Major tick
+ * spacing</td><td>Number</td><td>45</td><td>Degrees</td></tr>
+ * <tr><td>Starting angle</td><td>Number</td><td>180</td>
+ * <td>How far to rotate the entire dial, in degrees</td></tr>
+ * <tr><td>Show tick mark ring</td><td>Boolean</td><td>true</td></tr>
+ * </table>
+ */
+ static const WidgetType kGyro;
+ /**
+ * Displays a relay with toggle buttons for each supported mode (off, on,
+ * forward, reverse). <br>Supported types: <ul> <li>{@link
+ * edu.wpi.first.wpilibj.Relay}</li>
+ * </ul>
+ * <br>This widget has no custom properties.
+ */
+ static const WidgetType kRelay;
+ /**
+ * Displays a differential drive with a widget that displays the speed of each
+ * side of the drivebase and a vector for the direction and rotation of the
+ * drivebase. The widget will be controllable if the robot is in test mode.
+ * <br>Supported types:
+ * <ul>
+ * <li>{@link edu.wpi.first.wpilibj.drive.DifferentialDrive}</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Number of wheels</td><td>Number</td><td>4</td><td>Must be a
+ * positive even integer
+ * </td></tr>
+ * <tr><td>Wheel diameter</td><td>Number</td><td>80</td><td>Pixels</td></tr>
+ * <tr><td>Show velocity vectors</td><td>Boolean</td><td>true</td></tr>
+ * </table>
+ */
+ static const WidgetType kDifferentialDrive;
+ /**
+ * Displays a mecanum drive with a widget that displays the speed of each
+ * wheel, and vectors for the direction and rotation of the drivebase. The
+ * widget will be controllable if the robot is in test mode. <br>Supported
+ * types: <ul> <li>{@link edu.wpi.first.wpilibj.drive.MecanumDrive}</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Show velocity vectors</td><td>Boolean</td><td>true</td></tr>
+ * </table>
+ */
+ static const WidgetType kMecanumDrive;
+ /**
+ * Displays a camera stream.
+ * <br>Supported types:
+ * <ul>
+ * <li>{@link edu.wpi.cscore.VideoSource} (as long as it is streaming on an
+ * MJPEG server)</li>
+ * </ul>
+ * <br>Custom properties:
+ * <table>
+ * <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
+ * <tr><td>Show crosshair</td><td>Boolean</td><td>true</td>
+ * <td>Show or hide a crosshair on the image</td></tr>
+ * <tr><td>Crosshair color</td><td>Color</td><td>"white"</td>
+ * <td>Can be a string or a rgba integer</td></tr>
+ * <tr><td>Show controls</td><td>Boolean</td><td>true</td><td>Show or hide the
+ * stream controls
+ * </td></tr>
+ * <tr><td>Rotation</td><td>String</td><td>"NONE"</td>
+ * <td>Rotates the displayed image. One of {@code ["NONE", "QUARTER_CW",
+ * "QUARTER_CCW", "HALF"]}
+ * </td></tr>
+ * </table>
+ */
+ static const WidgetType kCameraStream;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ComplexWidget.h b/wpilibc/src/main/native/include/frc/shuffleboard/ComplexWidget.h
new file mode 100644
index 0000000..218ed2f
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ComplexWidget.h
@@ -0,0 +1,46 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <networktables/NetworkTable.h>
+#include <wpi/Twine.h>
+
+#include "frc/shuffleboard/ShuffleboardWidget.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+#include "frc/smartdashboard/SendableBuilderImpl.h"
+
+namespace frc {
+
+class Sendable;
+class ShuffleboardContainer;
+
+/**
+ * A Shuffleboard widget that handles a {@link Sendable} object such as a speed
+ * controller or sensor.
+ */
+class ComplexWidget final : public ShuffleboardWidget<ComplexWidget> {
+ public:
+ ComplexWidget(ShuffleboardContainer& parent, const wpi::Twine& title,
+ Sendable& sendable);
+
+ void EnableIfActuator() override;
+
+ void DisableIfActuator() override;
+
+ void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
+ std::shared_ptr<nt::NetworkTable> metaTable) override;
+
+ private:
+ Sendable& m_sendable;
+ SendableBuilderImpl m_builder;
+ bool m_builderInit = false;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/LayoutType.h b/wpilibc/src/main/native/include/frc/shuffleboard/LayoutType.h
new file mode 100644
index 0000000..22fe361
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/LayoutType.h
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/Twine.h>
+
+namespace frc {
+
+/**
+ * Represents the type of a layout in Shuffleboard. Using this is preferred over
+ * specifying raw strings, to avoid typos and having to know or look up the
+ * exact string name for a desired layout.
+ *
+ * @see BuiltInLayouts the built-in layout types
+ */
+class LayoutType {
+ public:
+ explicit LayoutType(const char* layoutName) : m_layoutName(layoutName) {}
+ ~LayoutType() = default;
+
+ /**
+ * Gets the string type of the layout as defined by that layout in
+ * Shuffleboard.
+ */
+ wpi::StringRef GetLayoutName() const;
+
+ private:
+ wpi::StringRef m_layoutName;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/RecordingController.h b/wpilibc/src/main/native/include/frc/shuffleboard/RecordingController.h
new file mode 100644
index 0000000..dacbdb4
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/RecordingController.h
@@ -0,0 +1,43 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include <networktables/NetworkTable.h>
+#include <networktables/NetworkTableInstance.h>
+#include <wpi/SmallVector.h>
+#include <wpi/StringRef.h>
+
+#include "frc/shuffleboard/ShuffleboardEventImportance.h"
+
+namespace frc {
+namespace detail {
+
+class RecordingController final {
+ public:
+ explicit RecordingController(nt::NetworkTableInstance ntInstance);
+ virtual ~RecordingController() = default;
+
+ void StartRecording();
+ void StopRecording();
+ void SetRecordingFileNameFormat(wpi::StringRef format);
+ void ClearRecordingFileNameFormat();
+
+ void AddEventMarker(wpi::StringRef name, wpi::StringRef description,
+ ShuffleboardEventImportance importance);
+
+ private:
+ nt::NetworkTableEntry m_recordingControlEntry;
+ nt::NetworkTableEntry m_recordingFileNameFormatEntry;
+ std::shared_ptr<nt::NetworkTable> m_eventsTable;
+};
+
+} // namespace detail
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/SendableCameraWrapper.h b/wpilibc/src/main/native/include/frc/shuffleboard/SendableCameraWrapper.h
new file mode 100644
index 0000000..291e64d
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/SendableCameraWrapper.h
@@ -0,0 +1,55 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <string>
+
+#include <cscore_c.h>
+
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace cs {
+class VideoSource;
+} // namespace cs
+
+namespace frc {
+
+/**
+ * A wrapper to make video sources sendable and usable from Shuffleboard.
+ */
+class SendableCameraWrapper : public SendableBase {
+ private:
+ struct private_init {};
+
+ public:
+ /**
+ * Creates a new sendable wrapper. Private constructor to avoid direct
+ * instantiation with multiple wrappers floating around for the same camera.
+ *
+ * @param source the source to wrap
+ */
+ SendableCameraWrapper(CS_Source source, const private_init&);
+
+ /**
+ * Gets a sendable wrapper object for the given video source, creating the
+ * wrapper if one does not already exist for the source.
+ *
+ * @param source the video source to wrap
+ * @return a sendable wrapper object for the video source, usable in
+ * Shuffleboard via ShuffleboardTab::Add() and ShuffleboardLayout::Add()
+ */
+ static SendableCameraWrapper& Wrap(const cs::VideoSource& source);
+ static SendableCameraWrapper& Wrap(CS_Source source);
+
+ void InitSendable(SendableBuilder& builder) override;
+
+ private:
+ std::string m_uri;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/Shuffleboard.h b/wpilibc/src/main/native/include/frc/shuffleboard/Shuffleboard.h
new file mode 100644
index 0000000..e49d1c3
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/Shuffleboard.h
@@ -0,0 +1,198 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/StringRef.h>
+
+#include "frc/shuffleboard/RecordingController.h"
+#include "frc/shuffleboard/ShuffleboardEventImportance.h"
+#include "frc/shuffleboard/ShuffleboardInstance.h"
+
+namespace frc {
+
+class ShuffleboardTab;
+
+/**
+ * The Shuffleboard class provides a mechanism with which data can be added and
+ * laid out in the Shuffleboard dashboard application from a robot program. Tabs
+ * and layouts can be specified, as well as choosing which widgets to display
+ * with and setting properties of these widgets; for example, programmers can
+ * specify a specific {@code boolean} value to be displayed with a toggle button
+ * instead of the default colored box, or set custom colors for that box.
+ *
+ * For example, displaying a boolean entry with a toggle button:
+ * <pre>{@code
+ * NetworkTableEntry myBoolean = Shuffleboard.getTab("Example Tab")
+ * .add("My Boolean", false)
+ * .withWidget("Toggle Button")
+ * .getEntry();
+ * }</pre>
+ *
+ * Changing the colors of the boolean box:
+ * <pre>{@code
+ * NetworkTableEntry myBoolean = Shuffleboard.getTab("Example Tab")
+ * .add("My Boolean", false)
+ * .withWidget("Boolean Box")
+ * .withProperties(Map.of("colorWhenTrue", "green", "colorWhenFalse",
+ * "maroon")) .getEntry();
+ * }</pre>
+ *
+ * Specifying a parent layout. Note that the layout type must <i>always</i> be
+ * specified, even if the layout has already been generated by a previously
+ * defined entry.
+ * <pre>{@code
+ * NetworkTableEntry myBoolean = Shuffleboard.getTab("Example Tab")
+ * .getLayout("List", "Example List")
+ * .add("My Boolean", false)
+ * .withWidget("Toggle Button")
+ * .getEntry();
+ * }</pre>
+ * </p>
+ *
+ * Teams are encouraged to set up shuffleboard layouts at the start of the robot
+ * program.
+ */
+class Shuffleboard final {
+ public:
+ /**
+ * The name of the base NetworkTable into which all Shuffleboard data will be
+ * added.
+ */
+ static constexpr const char* kBaseTableName = "/Shuffleboard";
+
+ /**
+ * Updates all the values in Shuffleboard. Iterative and timed robots are
+ * pre-configured to call this method in the main robot loop; teams using
+ * custom robot base classes, or subclass SampleRobot, should make sure to
+ * call this repeatedly to keep data on the dashboard up to date.
+ */
+ static void Update();
+
+ /**
+ * Gets the Shuffleboard tab with the given title, creating it if it does not
+ * already exist.
+ *
+ * @param title the title of the tab
+ * @return the tab with the given title
+ */
+ static ShuffleboardTab& GetTab(wpi::StringRef title);
+
+ /**
+ * Selects the tab in the dashboard with the given index in the range
+ * [0..n-1], where <i>n</i> is the number of tabs in the dashboard at the time
+ * this method is called.
+ *
+ * @param index the index of the tab to select
+ */
+ static void SelectTab(int index);
+
+ /**
+ * Selects the tab in the dashboard with the given title.
+ *
+ * @param title the title of the tab to select
+ */
+ static void SelectTab(wpi::StringRef title);
+
+ /**
+ * Enables user control of widgets containing actuators: speed controllers,
+ * relays, etc. This should only be used when the robot is in test mode.
+ * IterativeRobotBase and SampleRobot are both configured to call this method
+ * when entering test mode; most users should not need to use this method
+ * directly.
+ */
+ static void EnableActuatorWidgets();
+
+ /**
+ * Disables user control of widgets containing actuators. For safety reasons,
+ * actuators should only be controlled while in test mode. IterativeRobotBase
+ * and SampleRobot are both configured to call this method when exiting in
+ * test mode; most users should not need to use this method directly.
+ */
+ static void DisableActuatorWidgets();
+
+ /**
+ * Starts data recording on the dashboard. Has no effect if recording is
+ * already in progress.
+ */
+ static void StartRecording();
+
+ /**
+ * Stops data recording on the dashboard. Has no effect if no recording is in
+ * progress.
+ */
+ static void StopRecording();
+
+ /**
+ * Sets the file name format for new recording files to use. If recording is
+ * in progress when this method is called, it will continue to use the same
+ * file. New recordings will use the format.
+ *
+ * <p>To avoid recording files overwriting each other, make sure to use unique
+ * recording file names. File name formats accept templates for inserting the
+ * date and time when the recording started with the {@code ${date}} and
+ * {@code ${time}} templates, respectively. For example, the default format is
+ * {@code "recording-${time}"} and recording files created with it will have
+ * names like {@code "recording-2018.01.15.sbr"}. Users are
+ * <strong>strongly</strong> recommended to use the {@code ${time}} template
+ * to ensure unique file names.
+ * </p>
+ *
+ * @param format the format for the
+ */
+ static void SetRecordingFileNameFormat(wpi::StringRef format);
+
+ /**
+ * Clears the custom name format for recording files. New recordings will use
+ * the default format.
+ *
+ * @see #setRecordingFileNameFormat(String)
+ */
+ static void ClearRecordingFileNameFormat();
+
+ /**
+ * Notifies Shuffleboard of an event. Events can range from as trivial as a
+ * change in a command state to as critical as a total power loss or component
+ * failure. If Shuffleboard is recording, the event will also be recorded.
+ *
+ * <p>If {@code name} is {@code null} or empty, no event will be sent and an
+ * error will be printed to the driver station.
+ *
+ * @param name the name of the event
+ * @param description a description of the event
+ * @param importance the importance of the event
+ */
+ static void AddEventMarker(wpi::StringRef name, wpi::StringRef description,
+ ShuffleboardEventImportance importance);
+
+ /**
+ * Notifies Shuffleboard of an event. Events can range from as trivial as a
+ * change in a command state to as critical as a total power loss or component
+ * failure. If Shuffleboard is recording, the event will also be recorded.
+ *
+ * <p>If {@code name} is {@code null} or empty, no event will be sent and an
+ * error will be printed to the driver station.
+ *
+ * @param name the name of the event
+ * @param importance the importance of the event
+ */
+ static void AddEventMarker(wpi::StringRef name,
+ ShuffleboardEventImportance importance);
+
+ private:
+ static detail::ShuffleboardInstance& GetInstance();
+ static detail::RecordingController& GetRecordingController();
+
+ // TODO usage reporting
+
+ Shuffleboard() = default;
+};
+
+} // namespace frc
+
+// Make use of references returned by member functions usable
+#include "frc/shuffleboard/ShuffleboardTab.h"
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h
new file mode 100644
index 0000000..d6b4bc4
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h
@@ -0,0 +1,76 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include <networktables/NetworkTable.h>
+#include <networktables/NetworkTableValue.h>
+#include <wpi/StringMap.h>
+#include <wpi/Twine.h>
+
+#include "frc/shuffleboard/ShuffleboardComponentBase.h"
+
+namespace frc {
+
+class ShuffleboardContainer;
+
+/**
+ * A generic component in Shuffleboard.
+ *
+ * @tparam Derived the self type
+ */
+template <typename Derived>
+class ShuffleboardComponent : public ShuffleboardComponentBase {
+ public:
+ ShuffleboardComponent(ShuffleboardContainer& parent, const wpi::Twine& title,
+ const wpi::Twine& type = "");
+
+ virtual ~ShuffleboardComponent() = default;
+
+ /**
+ * Sets custom properties for this component. Property names are
+ * case-sensitive and whitespace-insensitive (capitalization and spaces do not
+ * matter).
+ *
+ * @param properties the properties for this component
+ * @return this component
+ */
+ Derived& WithProperties(
+ const wpi::StringMap<std::shared_ptr<nt::Value>>& properties);
+
+ /**
+ * Sets the position of this component in the tab. This has no effect if this
+ * component is inside a layout.
+ *
+ * If the position of a single component is set, it is recommended to set the
+ * positions of <i>all</i> components inside a tab to prevent Shuffleboard
+ * from automatically placing another component there before the one with the
+ * specific position is sent.
+ *
+ * @param columnIndex the column in the tab to place this component
+ * @param rowIndex the row in the tab to place this component
+ * @return this component
+ */
+ Derived& WithPosition(int columnIndex, int rowIndex);
+
+ /**
+ * Sets the size of this component in the tab. This has no effect if this
+ * component is inside a layout.
+ *
+ * @param width how many columns wide the component should be
+ * @param height how many rows high the component should be
+ * @return this component
+ */
+ Derived& WithSize(int width, int height);
+};
+
+} // namespace frc
+
+#include "frc/shuffleboard/ShuffleboardComponent.inc"
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.inc b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.inc
new file mode 100644
index 0000000..f75fb0d
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.inc
@@ -0,0 +1,47 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+namespace frc {
+
+template <typename Derived>
+ShuffleboardComponent<Derived>::ShuffleboardComponent(
+ ShuffleboardContainer& parent, const wpi::Twine& title,
+ const wpi::Twine& type)
+ : ShuffleboardValue(title),
+ ShuffleboardComponentBase(parent, title, type) {}
+
+template <typename Derived>
+Derived& ShuffleboardComponent<Derived>::WithProperties(
+ const wpi::StringMap<std::shared_ptr<nt::Value>>& properties) {
+ m_properties = properties;
+ m_metadataDirty = true;
+ return *static_cast<Derived*>(this);
+}
+
+template <typename Derived>
+Derived& ShuffleboardComponent<Derived>::WithPosition(int columnIndex,
+ int rowIndex) {
+ m_column = columnIndex;
+ m_row = rowIndex;
+ m_metadataDirty = true;
+ return *static_cast<Derived*>(this);
+}
+
+template <typename Derived>
+Derived& ShuffleboardComponent<Derived>::WithSize(int width, int height) {
+ m_width = width;
+ m_height = height;
+ m_metadataDirty = true;
+ return *static_cast<Derived*>(this);
+}
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponentBase.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponentBase.h
new file mode 100644
index 0000000..c63e517
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponentBase.h
@@ -0,0 +1,61 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include <networktables/NetworkTable.h>
+#include <networktables/NetworkTableValue.h>
+#include <wpi/StringMap.h>
+#include <wpi/Twine.h>
+
+#include "frc/shuffleboard/ShuffleboardValue.h"
+
+namespace frc {
+
+class ShuffleboardContainer;
+
+/**
+ * A shim class to allow storing ShuffleboardComponents in arrays.
+ */
+class ShuffleboardComponentBase : public virtual ShuffleboardValue {
+ public:
+ ShuffleboardComponentBase(ShuffleboardContainer& parent,
+ const wpi::Twine& title,
+ const wpi::Twine& type = "");
+
+ virtual ~ShuffleboardComponentBase() = default;
+
+ void SetType(const wpi::Twine& type);
+
+ void BuildMetadata(std::shared_ptr<nt::NetworkTable> metaTable);
+
+ ShuffleboardContainer& GetParent();
+
+ const std::string& GetType() const;
+
+ protected:
+ wpi::StringMap<std::shared_ptr<nt::Value>> m_properties;
+ bool m_metadataDirty = true;
+ int m_column = -1;
+ int m_row = -1;
+ int m_width = -1;
+ int m_height = -1;
+
+ private:
+ ShuffleboardContainer& m_parent;
+ std::string m_type;
+
+ /**
+ * Gets the custom properties for this component. May be null.
+ */
+ const wpi::StringMap<std::shared_ptr<nt::Value>>& GetProperties() const;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h
new file mode 100644
index 0000000..e53bcfc
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h
@@ -0,0 +1,398 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <networktables/NetworkTableEntry.h>
+#include <networktables/NetworkTableValue.h>
+#include <wpi/ArrayRef.h>
+#include <wpi/SmallSet.h>
+#include <wpi/StringMap.h>
+#include <wpi/Twine.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/WPIErrors.h"
+#include "frc/shuffleboard/LayoutType.h"
+#include "frc/shuffleboard/ShuffleboardComponentBase.h"
+#include "frc/shuffleboard/ShuffleboardValue.h"
+
+namespace cs {
+class VideoSource;
+} // namespace cs
+
+namespace frc {
+
+class ComplexWidget;
+class Sendable;
+class ShuffleboardLayout;
+class SimpleWidget;
+
+/**
+ * Common interface for objects that can contain shuffleboard components.
+ */
+class ShuffleboardContainer : public virtual ShuffleboardValue,
+ public ErrorBase {
+ public:
+ explicit ShuffleboardContainer(const wpi::Twine& title);
+
+ ShuffleboardContainer(ShuffleboardContainer&& rhs) = default;
+
+ virtual ~ShuffleboardContainer() = default;
+
+ /**
+ * Gets the components that are direct children of this container.
+ */
+ const std::vector<std::unique_ptr<ShuffleboardComponentBase>>& GetComponents()
+ const;
+
+ /**
+ * Gets the layout with the given type and title, creating it if it does not
+ * already exist at the time this method is called.
+ *
+ * @param title the title of the layout
+ * @param layoutType the type of the layout, eg "List" or "Grid"
+ * @return the layout
+ */
+ ShuffleboardLayout& GetLayout(const wpi::Twine& title,
+ const LayoutType& type);
+
+ /**
+ * Gets the layout with the given type and title, creating it if it does not
+ * already exist at the time this method is called. Note: this method should
+ * only be used to use a layout type that is not already built into
+ * Shuffleboard. To use a layout built into Shuffleboard, use
+ * {@link #GetLayout(String, LayoutType)} and the layouts in {@link
+ * BuiltInLayouts}.
+ *
+ * @param title the title of the layout
+ * @param type the type of the layout, eg "List Layout" or "Grid Layout"
+ * @return the layout
+ * @see #GetLayout(String, LayoutType)
+ */
+ ShuffleboardLayout& GetLayout(const wpi::Twine& title,
+ const wpi::Twine& type);
+
+ /**
+ * Gets the already-defined layout in this container with the given title.
+ *
+ * <pre>{@code
+ * Shuffleboard::GetTab("Example Tab")->getLayout("My Layout",
+ * &BuiltInLayouts.kList);
+ *
+ * // Later...
+ * Shuffleboard::GetTab("Example Tab")->GetLayout("My Layout");
+ * }</pre>
+ *
+ * @param title the title of the layout to get
+ * @return the layout with the given title
+ * @throws if no layout has yet been defined with the given title
+ */
+ ShuffleboardLayout& GetLayout(const wpi::Twine& title);
+
+ /**
+ * Adds a widget to this container to display the given sendable.
+ *
+ * @param title the title of the widget
+ * @param sendable the sendable to display
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ */
+ ComplexWidget& Add(const wpi::Twine& title, Sendable& sendable);
+
+ /**
+ * Adds a widget to this container to display the given video stream.
+ *
+ * @param title the title of the widget
+ * @param video the video stream to display
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ */
+ ComplexWidget& Add(const wpi::Twine& title, const cs::VideoSource& video);
+
+ /**
+ * Adds a widget to this container to display the given sendable.
+ *
+ * @param sendable the sendable to display
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title, or if the sendable's name has not been
+ * specified
+ */
+ ComplexWidget& Add(Sendable& sendable);
+
+ /**
+ * Adds a widget to this container to display the given video stream.
+ *
+ * @param video the video to display
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the same title as the video source
+ */
+ ComplexWidget& Add(const cs::VideoSource& video);
+
+ /**
+ * Adds a widget to this container to display the given data.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ * @see #addPersistent(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& Add(const wpi::Twine& title,
+ std::shared_ptr<nt::Value> defaultValue);
+
+ /**
+ * Adds a widget to this container to display the given data.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ * @see #addPersistent(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& Add(const wpi::Twine& title, bool defaultValue);
+
+ /**
+ * Adds a widget to this container to display the given data.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ * @see #addPersistent(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& Add(const wpi::Twine& title, double defaultValue);
+
+ /**
+ * Adds a widget to this container to display the given data.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ * @see #addPersistent(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& Add(const wpi::Twine& title, int defaultValue);
+
+ /**
+ * Adds a widget to this container to display the given data.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ * @see #addPersistent(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& Add(const wpi::Twine& title, const wpi::Twine& defaultValue);
+
+ /**
+ * Adds a widget to this container to display the given data.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ * @see #addPersistent(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& Add(const wpi::Twine& title, const char* defaultValue);
+
+ /**
+ * Adds a widget to this container to display the given data.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ * @see #addPersistent(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& Add(const wpi::Twine& title, wpi::ArrayRef<bool> defaultValue);
+
+ /**
+ * Adds a widget to this container to display the given data.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ * @see #addPersistent(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& Add(const wpi::Twine& title,
+ wpi::ArrayRef<double> defaultValue);
+
+ /**
+ * Adds a widget to this container to display the given data.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @throws IllegalArgumentException if a widget already exists in this
+ * container with the given title
+ * @see #addPersistent(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& Add(const wpi::Twine& title,
+ wpi::ArrayRef<std::string> defaultValue);
+
+ /**
+ * Adds a widget to this container to display a simple piece of data.
+ *
+ * Unlike {@link #add(String, Object)}, the value in the widget will be saved
+ * on the robot and will be used when the robot program next starts rather
+ * than {@code defaultValue}.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @see #add(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& AddPersistent(const wpi::Twine& title,
+ std::shared_ptr<nt::Value> defaultValue);
+
+ /**
+ * Adds a widget to this container to display a simple piece of data.
+ *
+ * Unlike {@link #add(String, Object)}, the value in the widget will be saved
+ * on the robot and will be used when the robot program next starts rather
+ * than {@code defaultValue}.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @see #add(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& AddPersistent(const wpi::Twine& title, bool defaultValue);
+
+ /**
+ * Adds a widget to this container to display a simple piece of data.
+ *
+ * Unlike {@link #add(String, Object)}, the value in the widget will be saved
+ * on the robot and will be used when the robot program next starts rather
+ * than {@code defaultValue}.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @see #add(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& AddPersistent(const wpi::Twine& title, double defaultValue);
+
+ /**
+ * Adds a widget to this container to display a simple piece of data.
+ *
+ * Unlike {@link #add(String, Object)}, the value in the widget will be saved
+ * on the robot and will be used when the robot program next starts rather
+ * than {@code defaultValue}.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @see #add(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& AddPersistent(const wpi::Twine& title, int defaultValue);
+
+ /**
+ * Adds a widget to this container to display a simple piece of data.
+ *
+ * Unlike {@link #add(String, Object)}, the value in the widget will be saved
+ * on the robot and will be used when the robot program next starts rather
+ * than {@code defaultValue}.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @see #add(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& AddPersistent(const wpi::Twine& title,
+ const wpi::Twine& defaultValue);
+
+ /**
+ * Adds a widget to this container to display a simple piece of data.
+ *
+ * Unlike {@link #add(String, Object)}, the value in the widget will be saved
+ * on the robot and will be used when the robot program next starts rather
+ * than {@code defaultValue}.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @see #add(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& AddPersistent(const wpi::Twine& title,
+ wpi::ArrayRef<bool> defaultValue);
+
+ /**
+ * Adds a widget to this container to display a simple piece of data.
+ *
+ * Unlike {@link #add(String, Object)}, the value in the widget will be saved
+ * on the robot and will be used when the robot program next starts rather
+ * than {@code defaultValue}.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @see #add(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& AddPersistent(const wpi::Twine& title,
+ wpi::ArrayRef<double> defaultValue);
+
+ /**
+ * Adds a widget to this container to display a simple piece of data.
+ *
+ * Unlike {@link #add(String, Object)}, the value in the widget will be saved
+ * on the robot and will be used when the robot program next starts rather
+ * than {@code defaultValue}.
+ *
+ * @param title the title of the widget
+ * @param defaultValue the default value of the widget
+ * @return a widget to display the sendable data
+ * @see #add(String, Object) add(String title, Object defaultValue)
+ */
+ SimpleWidget& AddPersistent(const wpi::Twine& title,
+ wpi::ArrayRef<std::string> defaultValue);
+
+ void EnableIfActuator() override;
+
+ void DisableIfActuator() override;
+
+ protected:
+ bool m_isLayout = false;
+
+ private:
+ wpi::SmallSet<std::string, 32> m_usedTitles;
+ std::vector<std::unique_ptr<ShuffleboardComponentBase>> m_components;
+ wpi::StringMap<ShuffleboardLayout*> m_layouts;
+
+ /**
+ * Adds title to internal set if it hasn't already.
+ *
+ * @return True if title isn't in use; false otherwise.
+ */
+ void CheckTitle(const wpi::Twine& title);
+
+ friend class SimpleWidget;
+};
+
+} // namespace frc
+
+// Make use of references returned by member functions usable
+#include "frc/shuffleboard/ComplexWidget.h"
+#include "frc/shuffleboard/ShuffleboardLayout.h"
+#include "frc/shuffleboard/SimpleWidget.h"
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardEventImportance.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardEventImportance.h
new file mode 100644
index 0000000..ccbc802
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardEventImportance.h
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+namespace frc {
+
+// Maintainer note: this enum is mirrored in WPILibJ and in Shuffleboard
+// Modifying the enum or enum strings requires a corresponding change to the
+// Java enum and the enum in Shuffleboard
+
+enum ShuffleboardEventImportance { kTrivial, kLow, kNormal, kHigh, kCritical };
+
+inline wpi::StringRef ShuffleboardEventImportanceName(
+ ShuffleboardEventImportance importance) {
+ switch (importance) {
+ case kTrivial:
+ return "TRIVIAL";
+ case kLow:
+ return "LOW";
+ case kNormal:
+ return "NORMAL";
+ case kHigh:
+ return "HIGH";
+ case kCritical:
+ return "CRITICAL";
+ default:
+ return "NORMAL";
+ }
+}
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardInstance.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardInstance.h
new file mode 100644
index 0000000..b202160
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardInstance.h
@@ -0,0 +1,41 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include "frc/shuffleboard/ShuffleboardRoot.h"
+#include "frc/shuffleboard/ShuffleboardTab.h"
+
+namespace frc {
+namespace detail {
+
+class ShuffleboardInstance final : public ShuffleboardRoot {
+ public:
+ explicit ShuffleboardInstance(nt::NetworkTableInstance ntInstance);
+ virtual ~ShuffleboardInstance();
+
+ frc::ShuffleboardTab& GetTab(wpi::StringRef title) override;
+
+ void Update() override;
+
+ void EnableActuatorWidgets() override;
+
+ void DisableActuatorWidgets() override;
+
+ void SelectTab(int index) override;
+
+ void SelectTab(wpi::StringRef) override;
+
+ private:
+ struct Impl;
+ std::unique_ptr<Impl> m_impl;
+};
+
+} // namespace detail
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardLayout.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardLayout.h
new file mode 100644
index 0000000..0b5d459
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardLayout.h
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <networktables/NetworkTable.h>
+#include <wpi/Twine.h>
+
+#include "frc/shuffleboard/ShuffleboardComponent.h"
+#include "frc/shuffleboard/ShuffleboardContainer.h"
+#include "frc/smartdashboard/Sendable.h"
+
+namespace frc {
+
+/**
+ * A layout in a Shuffleboard tab. Layouts can contain widgets and other
+ * layouts.
+ */
+class ShuffleboardLayout : public ShuffleboardComponent<ShuffleboardLayout>,
+ public ShuffleboardContainer {
+ public:
+ ShuffleboardLayout(ShuffleboardContainer& parent, const wpi::Twine& name,
+ const wpi::Twine& type);
+
+ void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
+ std::shared_ptr<nt::NetworkTable> metaTable) override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardRoot.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardRoot.h
new file mode 100644
index 0000000..0c50545
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardRoot.h
@@ -0,0 +1,66 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/StringRef.h>
+
+namespace frc {
+
+class ShuffleboardTab;
+
+/**
+ * The root of the data placed in Shuffleboard. It contains the tabs, but no
+ * data is placed directly in the root.
+ *
+ * This class is package-private to minimize API surface area.
+ */
+class ShuffleboardRoot {
+ public:
+ /**
+ * Gets the tab with the given title, creating it if it does not already
+ * exist.
+ *
+ * @param title the title of the tab
+ * @return the tab with the given title
+ */
+ virtual ShuffleboardTab& GetTab(wpi::StringRef title) = 0;
+
+ /**
+ * Updates all tabs.
+ */
+ virtual void Update() = 0;
+
+ /**
+ * Enables all widgets in Shuffleboard that offer user control over actuators.
+ */
+ virtual void EnableActuatorWidgets() = 0;
+
+ /**
+ * Disables all widgets in Shuffleboard that offer user control over
+ * actuators.
+ */
+ virtual void DisableActuatorWidgets() = 0;
+
+ /**
+ * Selects the tab in the dashboard with the given index in the range
+ * [0..n-1], where <i>n</i> is the number of tabs in the dashboard at the time
+ * this method is called.
+ *
+ * @param index the index of the tab to select
+ */
+ virtual void SelectTab(int index) = 0;
+
+ /**
+ * Selects the tab in the dashboard with the given title.
+ *
+ * @param title the title of the tab to select
+ */
+ virtual void SelectTab(wpi::StringRef title) = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardTab.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardTab.h
new file mode 100644
index 0000000..16e6f92
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardTab.h
@@ -0,0 +1,42 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <networktables/NetworkTable.h>
+#include <wpi/StringRef.h>
+
+#include "frc/shuffleboard/ShuffleboardContainer.h"
+#include "frc/smartdashboard/Sendable.h"
+
+namespace frc {
+
+class ShuffleboardRoot;
+
+/**
+ * Represents a tab in the Shuffleboard dashboard. Widgets can be added to the
+ * tab with {@link #add(Sendable)}, {@link #add(String, Object)}, and
+ * {@link #add(String, Sendable)}. Widgets can also be added to layouts with
+ * {@link #getLayout(String, String)}; layouts can be nested arbitrarily deep
+ * (note that too many levels may make deeper components unusable).
+ */
+class ShuffleboardTab final : public ShuffleboardContainer {
+ public:
+ ShuffleboardTab(ShuffleboardRoot& root, wpi::StringRef title);
+
+ ShuffleboardRoot& GetRoot();
+
+ void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
+ std::shared_ptr<nt::NetworkTable> metaTable) override;
+
+ private:
+ ShuffleboardRoot& m_root;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardValue.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardValue.h
new file mode 100644
index 0000000..4a88cc1
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardValue.h
@@ -0,0 +1,71 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include <networktables/NetworkTable.h>
+#include <wpi/SmallVector.h>
+#include <wpi/StringRef.h>
+
+namespace frc {
+
+class ShuffleboardValue {
+ public:
+ explicit ShuffleboardValue(const wpi::Twine& title) {
+ wpi::SmallVector<char, 16> storage;
+ m_title = title.toStringRef(storage);
+ }
+
+ virtual ~ShuffleboardValue() = default;
+
+ /**
+ * Gets the title of this Shuffleboard value.
+ */
+ wpi::StringRef GetTitle() const { return m_title; }
+
+ /**
+ * Builds the entries for this value.
+ *
+ * @param parentTable The table containing all the data for the parent. Values
+ * that require a complex entry or table structure should
+ * call {@code parentTable.getSubtable(getTitle())} to get
+ * the table to put data into. Values that only use a
+ * single entry should call
+ * {@code parentTable.getEntry(getTitle())} to get that
+ * entry.
+ * @param metaTable The table containing all the metadata for this value and
+ * its sub-values
+ */
+ virtual void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
+ std::shared_ptr<nt::NetworkTable> metaTable) = 0;
+
+ /**
+ * Enables user control of this widget in the Shuffleboard application.
+ *
+ * This method is package-private to prevent users from enabling control
+ * themselves. Has no effect if the sendable is not marked as an actuator with
+ * {@link SendableBuilder#setActuator}.
+ */
+ virtual void EnableIfActuator() {}
+
+ /**
+ * Disables user control of this widget in the Shuffleboard application.
+ *
+ * This method is package-private to prevent users from enabling control
+ * themselves. Has no effect if the sendable is not marked as an actuator with
+ * {@link SendableBuilder#setActuator}.
+ */
+ virtual void DisableIfActuator() {}
+
+ private:
+ std::string m_title;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardWidget.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardWidget.h
new file mode 100644
index 0000000..2e67160
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardWidget.h
@@ -0,0 +1,63 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/Twine.h>
+
+#include "frc/shuffleboard/ShuffleboardComponent.h"
+#include "frc/shuffleboard/WidgetType.h"
+
+namespace frc {
+
+class ShuffleboardContainer;
+
+/**
+ * Abstract superclass for widgets.
+ *
+ * <p>This class is package-private to minimize API surface area.
+ *
+ * @tparam Derived the self type
+ */
+template <typename Derived>
+class ShuffleboardWidget
+ : public ShuffleboardComponent<ShuffleboardWidget<Derived>> {
+ public:
+ ShuffleboardWidget(ShuffleboardContainer& parent, const wpi::Twine& title)
+ : ShuffleboardValue(title),
+ ShuffleboardComponent<ShuffleboardWidget<Derived>>(parent, title) {}
+
+ /**
+ * Sets the type of widget used to display the data. If not set, the default
+ * widget type will be used.
+ *
+ * @param widgetType the type of the widget used to display the data
+ * @return this widget object
+ * @see BuiltInWidgets
+ */
+ Derived& withWidget(const WidgetType& widgetType) {
+ return WithWidget(widgetType.GetWidgetName());
+ }
+
+ /**
+ * Sets the type of widget used to display the data. If not set, the default
+ * widget type will be used. This method should only be used to use a widget
+ * that does not come built into Shuffleboard (i.e. one that comes with a
+ * custom or thrid-party plugin). To use a widget that is built into
+ * Shuffleboard, use {@link #withWidget(WidgetType)} and {@link
+ * BuiltInWidgets}.
+ *
+ * @param widgetType the type of the widget used to display the data
+ * @return this widget object
+ */
+ Derived& WithWidget(const wpi::Twine& widgetType) {
+ this->SetType(widgetType);
+ return *static_cast<Derived*>(this);
+ }
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/SimpleWidget.h b/wpilibc/src/main/native/include/frc/shuffleboard/SimpleWidget.h
new file mode 100644
index 0000000..973f8cb
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/SimpleWidget.h
@@ -0,0 +1,44 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <networktables/NetworkTable.h>
+#include <networktables/NetworkTableEntry.h>
+#include <wpi/Twine.h>
+
+#include "frc/shuffleboard/ShuffleboardWidget.h"
+
+namespace frc {
+
+class ShuffleboardContainer;
+
+/**
+ * A Shuffleboard widget that handles a single data point such as a number or
+ * string.
+ */
+class SimpleWidget final : public ShuffleboardWidget<SimpleWidget> {
+ public:
+ SimpleWidget(ShuffleboardContainer& parent, const wpi::Twine& title);
+
+ /**
+ * Gets the NetworkTable entry that contains the data for this widget.
+ */
+ nt::NetworkTableEntry GetEntry();
+
+ void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
+ std::shared_ptr<nt::NetworkTable> metaTable) override;
+
+ private:
+ nt::NetworkTableEntry m_entry;
+
+ void ForceGenerate();
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/WidgetType.h b/wpilibc/src/main/native/include/frc/shuffleboard/WidgetType.h
new file mode 100644
index 0000000..f96e9b6
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/shuffleboard/WidgetType.h
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/Twine.h>
+
+namespace frc {
+
+/**
+ * Represents the type of a widget in Shuffleboard. Using this is preferred over
+ * specifying raw strings, to avoid typos and having to know or look up the
+ * exact string name for a desired widget.
+ *
+ * @see BuiltInWidgets the built-in widget types
+ */
+class WidgetType {
+ public:
+ explicit WidgetType(const char* widgetName) : m_widgetName(widgetName) {}
+ ~WidgetType() = default;
+
+ /**
+ * Gets the string type of the widget as defined by that widget in
+ * Shuffleboard.
+ */
+ wpi::StringRef GetWidgetName() const;
+
+ private:
+ wpi::StringRef m_widgetName;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/NamedSendable.h b/wpilibc/src/main/native/include/frc/smartdashboard/NamedSendable.h
new file mode 100644
index 0000000..604d2e0
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/NamedSendable.h
@@ -0,0 +1,34 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2012-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <string>
+
+#include <wpi/deprecated.h>
+
+#include "frc/smartdashboard/Sendable.h"
+
+namespace frc {
+
+/**
+ * The interface for sendable objects that gives the sendable a default name in
+ * the Smart Dashboard.
+ * @deprecated Use Sendable directly instead
+ */
+class NamedSendable : public Sendable {
+ public:
+ WPI_DEPRECATED("use Sendable directly instead")
+ NamedSendable() = default;
+
+ void SetName(const wpi::Twine& name) override;
+ std::string GetSubsystem() const override;
+ void SetSubsystem(const wpi::Twine& subsystem) override;
+ void InitSendable(SendableBuilder& builder) override;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/Sendable.h b/wpilibc/src/main/native/include/frc/smartdashboard/Sendable.h
new file mode 100644
index 0000000..383c169
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/Sendable.h
@@ -0,0 +1,73 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <string>
+
+#include <wpi/Twine.h>
+
+namespace frc {
+
+class SendableBuilder;
+
+class Sendable {
+ public:
+ Sendable() = default;
+ virtual ~Sendable() = default;
+
+ Sendable(Sendable&&) = default;
+ Sendable& operator=(Sendable&&) = default;
+
+ /**
+ * Gets the name of this Sendable object.
+ *
+ * @return Name
+ */
+ virtual std::string GetName() const = 0;
+
+ /**
+ * Sets the name of this Sendable object.
+ *
+ * @param name name
+ */
+ virtual void SetName(const wpi::Twine& name) = 0;
+
+ /**
+ * Sets both the subsystem name and device name of this Sendable object.
+ *
+ * @param subsystem subsystem name
+ * @param name device name
+ */
+ void SetName(const wpi::Twine& subsystem, const wpi::Twine& name) {
+ SetSubsystem(subsystem);
+ SetName(name);
+ }
+
+ /**
+ * Gets the subsystem name of this Sendable object.
+ *
+ * @return Subsystem name
+ */
+ virtual std::string GetSubsystem() const = 0;
+
+ /**
+ * Sets the subsystem name of this Sendable object.
+ *
+ * @param subsystem subsystem name
+ */
+ virtual void SetSubsystem(const wpi::Twine& subsystem) = 0;
+
+ /**
+ * Initializes this Sendable object.
+ *
+ * @param builder sendable builder
+ */
+ virtual void InitSendable(SendableBuilder& builder) = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableBase.h b/wpilibc/src/main/native/include/frc/smartdashboard/SendableBase.h
new file mode 100644
index 0000000..6d2fbbe
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableBase.h
@@ -0,0 +1,81 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include <wpi/mutex.h>
+
+#include "frc/smartdashboard/Sendable.h"
+
+namespace frc {
+
+class SendableBase : public Sendable {
+ public:
+ /**
+ * Creates an instance of the sensor base.
+ *
+ * @param addLiveWindow if true, add this Sendable to LiveWindow
+ */
+ explicit SendableBase(bool addLiveWindow = true);
+
+ ~SendableBase() override;
+
+ SendableBase(SendableBase&& rhs);
+ SendableBase& operator=(SendableBase&& rhs);
+
+ using Sendable::SetName;
+
+ std::string GetName() const final;
+ void SetName(const wpi::Twine& name) final;
+ std::string GetSubsystem() const final;
+ void SetSubsystem(const wpi::Twine& subsystem) final;
+
+ protected:
+ /**
+ * Add a child component.
+ *
+ * @param child child component
+ */
+ void AddChild(std::shared_ptr<Sendable> child);
+
+ /**
+ * Add a child component.
+ *
+ * @param child child component
+ */
+ void AddChild(void* child);
+
+ /**
+ * Sets the name of the sensor with a channel number.
+ *
+ * @param moduleType A string that defines the module name in the label for
+ * the value
+ * @param channel The channel number the device is plugged into
+ */
+ void SetName(const wpi::Twine& moduleType, int channel);
+
+ /**
+ * Sets the name of the sensor with a module and channel number.
+ *
+ * @param moduleType A string that defines the module name in the label for
+ * the value
+ * @param moduleNumber The number of the particular module type
+ * @param channel The channel number the device is plugged into (usually
+ * PWM)
+ */
+ void SetName(const wpi::Twine& moduleType, int moduleNumber, int channel);
+
+ private:
+ mutable wpi::mutex m_mutex;
+ std::string m_name;
+ std::string m_subsystem = "Ungrouped";
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilder.h b/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilder.h
new file mode 100644
index 0000000..3f5f892
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilder.h
@@ -0,0 +1,222 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <networktables/NetworkTableEntry.h>
+#include <networktables/NetworkTableValue.h>
+#include <wpi/ArrayRef.h>
+#include <wpi/SmallVector.h>
+#include <wpi/Twine.h>
+
+namespace frc {
+
+class SendableBuilder {
+ public:
+ virtual ~SendableBuilder() = default;
+
+ /**
+ * Set the string representation of the named data type that will be used
+ * by the smart dashboard for this sendable.
+ *
+ * @param type data type
+ */
+ virtual void SetSmartDashboardType(const wpi::Twine& type) = 0;
+
+ /**
+ * Set a flag indicating if this sendable should be treated as an actuator.
+ * By default this flag is false.
+ *
+ * @param value true if actuator, false if not
+ */
+ virtual void SetActuator(bool value) = 0;
+
+ /**
+ * Set the function that should be called to set the Sendable into a safe
+ * state. This is called when entering and exiting Live Window mode.
+ *
+ * @param func function
+ */
+ virtual void SetSafeState(std::function<void()> func) = 0;
+
+ /**
+ * Set the function that should be called to update the network table
+ * for things other than properties. Note this function is not passed
+ * the network table object; instead it should use the entry handles
+ * returned by GetEntry().
+ *
+ * @param func function
+ */
+ virtual void SetUpdateTable(std::function<void()> func) = 0;
+
+ /**
+ * Add a property without getters or setters. This can be used to get
+ * entry handles for the function called by SetUpdateTable().
+ *
+ * @param key property name
+ * @return Network table entry
+ */
+ virtual nt::NetworkTableEntry GetEntry(const wpi::Twine& key) = 0;
+
+ /**
+ * Add a boolean property.
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddBooleanProperty(const wpi::Twine& key,
+ std::function<bool()> getter,
+ std::function<void(bool)> setter) = 0;
+
+ /**
+ * Add a double property.
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddDoubleProperty(const wpi::Twine& key,
+ std::function<double()> getter,
+ std::function<void(double)> setter) = 0;
+
+ /**
+ * Add a string property.
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddStringProperty(
+ const wpi::Twine& key, std::function<std::string()> getter,
+ std::function<void(wpi::StringRef)> setter) = 0;
+
+ /**
+ * Add a boolean array property.
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddBooleanArrayProperty(
+ const wpi::Twine& key, std::function<std::vector<int>()> getter,
+ std::function<void(wpi::ArrayRef<int>)> setter) = 0;
+
+ /**
+ * Add a double array property.
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddDoubleArrayProperty(
+ const wpi::Twine& key, std::function<std::vector<double>()> getter,
+ std::function<void(wpi::ArrayRef<double>)> setter) = 0;
+
+ /**
+ * Add a string array property.
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddStringArrayProperty(
+ const wpi::Twine& key, std::function<std::vector<std::string>()> getter,
+ std::function<void(wpi::ArrayRef<std::string>)> setter) = 0;
+
+ /**
+ * Add a raw property.
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddRawProperty(const wpi::Twine& key,
+ std::function<std::string()> getter,
+ std::function<void(wpi::StringRef)> setter) = 0;
+
+ /**
+ * Add a NetworkTableValue property.
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddValueProperty(
+ const wpi::Twine& key, std::function<std::shared_ptr<nt::Value>()> getter,
+ std::function<void(std::shared_ptr<nt::Value>)> setter) = 0;
+
+ /**
+ * Add a string property (SmallString form).
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddSmallStringProperty(
+ const wpi::Twine& key,
+ std::function<wpi::StringRef(wpi::SmallVectorImpl<char>& buf)> getter,
+ std::function<void(wpi::StringRef)> setter) = 0;
+
+ /**
+ * Add a boolean array property (SmallVector form).
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddSmallBooleanArrayProperty(
+ const wpi::Twine& key,
+ std::function<wpi::ArrayRef<int>(wpi::SmallVectorImpl<int>& buf)> getter,
+ std::function<void(wpi::ArrayRef<int>)> setter) = 0;
+
+ /**
+ * Add a double array property (SmallVector form).
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddSmallDoubleArrayProperty(
+ const wpi::Twine& key,
+ std::function<wpi::ArrayRef<double>(wpi::SmallVectorImpl<double>& buf)>
+ getter,
+ std::function<void(wpi::ArrayRef<double>)> setter) = 0;
+
+ /**
+ * Add a string array property (SmallVector form).
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddSmallStringArrayProperty(
+ const wpi::Twine& key,
+ std::function<
+ wpi::ArrayRef<std::string>(wpi::SmallVectorImpl<std::string>& buf)>
+ getter,
+ std::function<void(wpi::ArrayRef<std::string>)> setter) = 0;
+
+ /**
+ * Add a raw property (SmallVector form).
+ *
+ * @param key property name
+ * @param getter getter function (returns current value)
+ * @param setter setter function (sets new value)
+ */
+ virtual void AddSmallRawProperty(
+ const wpi::Twine& key,
+ std::function<wpi::StringRef(wpi::SmallVectorImpl<char>& buf)> getter,
+ std::function<void(wpi::StringRef)> setter) = 0;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilderImpl.h b/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilderImpl.h
new file mode 100644
index 0000000..e10f085
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilderImpl.h
@@ -0,0 +1,200 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <networktables/NetworkTable.h>
+#include <networktables/NetworkTableEntry.h>
+#include <networktables/NetworkTableValue.h>
+#include <wpi/ArrayRef.h>
+#include <wpi/SmallVector.h>
+#include <wpi/Twine.h>
+
+#include "frc/smartdashboard/SendableBuilder.h"
+
+namespace frc {
+
+class SendableBuilderImpl : public SendableBuilder {
+ public:
+ SendableBuilderImpl() = default;
+ ~SendableBuilderImpl() override = default;
+
+ SendableBuilderImpl(SendableBuilderImpl&&) = default;
+ SendableBuilderImpl& operator=(SendableBuilderImpl&&) = default;
+
+ /**
+ * Set the network table. Must be called prior to any Add* functions being
+ * called.
+ * @param table Network table
+ */
+ void SetTable(std::shared_ptr<nt::NetworkTable> table);
+
+ /**
+ * Get the network table.
+ * @return The network table
+ */
+ std::shared_ptr<nt::NetworkTable> GetTable();
+
+ /**
+ * Return whether this sendable should be treated as an actuator.
+ * @return True if actuator, false if not.
+ */
+ bool IsActuator() const;
+
+ /**
+ * Update the network table values by calling the getters for all properties.
+ */
+ void UpdateTable();
+
+ /**
+ * Hook setters for all properties.
+ */
+ void StartListeners();
+
+ /**
+ * Unhook setters for all properties.
+ */
+ void StopListeners();
+
+ /**
+ * Start LiveWindow mode by hooking the setters for all properties. Also
+ * calls the SafeState function if one was provided.
+ */
+ void StartLiveWindowMode();
+
+ /**
+ * Stop LiveWindow mode by unhooking the setters for all properties. Also
+ * calls the SafeState function if one was provided.
+ */
+ void StopLiveWindowMode();
+
+ void SetSmartDashboardType(const wpi::Twine& type) override;
+ void SetActuator(bool value) override;
+ void SetSafeState(std::function<void()> func) override;
+ void SetUpdateTable(std::function<void()> func) override;
+ nt::NetworkTableEntry GetEntry(const wpi::Twine& key) override;
+
+ void AddBooleanProperty(const wpi::Twine& key, std::function<bool()> getter,
+ std::function<void(bool)> setter) override;
+
+ void AddDoubleProperty(const wpi::Twine& key, std::function<double()> getter,
+ std::function<void(double)> setter) override;
+
+ void AddStringProperty(const wpi::Twine& key,
+ std::function<std::string()> getter,
+ std::function<void(wpi::StringRef)> setter) override;
+
+ void AddBooleanArrayProperty(
+ const wpi::Twine& key, std::function<std::vector<int>()> getter,
+ std::function<void(wpi::ArrayRef<int>)> setter) override;
+
+ void AddDoubleArrayProperty(
+ const wpi::Twine& key, std::function<std::vector<double>()> getter,
+ std::function<void(wpi::ArrayRef<double>)> setter) override;
+
+ void AddStringArrayProperty(
+ const wpi::Twine& key, std::function<std::vector<std::string>()> getter,
+ std::function<void(wpi::ArrayRef<std::string>)> setter) override;
+
+ void AddRawProperty(const wpi::Twine& key,
+ std::function<std::string()> getter,
+ std::function<void(wpi::StringRef)> setter) override;
+
+ void AddValueProperty(
+ const wpi::Twine& key, std::function<std::shared_ptr<nt::Value>()> getter,
+ std::function<void(std::shared_ptr<nt::Value>)> setter) override;
+
+ void AddSmallStringProperty(
+ const wpi::Twine& key,
+ std::function<wpi::StringRef(wpi::SmallVectorImpl<char>& buf)> getter,
+ std::function<void(wpi::StringRef)> setter) override;
+
+ void AddSmallBooleanArrayProperty(
+ const wpi::Twine& key,
+ std::function<wpi::ArrayRef<int>(wpi::SmallVectorImpl<int>& buf)> getter,
+ std::function<void(wpi::ArrayRef<int>)> setter) override;
+
+ void AddSmallDoubleArrayProperty(
+ const wpi::Twine& key,
+ std::function<wpi::ArrayRef<double>(wpi::SmallVectorImpl<double>& buf)>
+ getter,
+ std::function<void(wpi::ArrayRef<double>)> setter) override;
+
+ void AddSmallStringArrayProperty(
+ const wpi::Twine& key,
+ std::function<
+ wpi::ArrayRef<std::string>(wpi::SmallVectorImpl<std::string>& buf)>
+ getter,
+ std::function<void(wpi::ArrayRef<std::string>)> setter) override;
+
+ void AddSmallRawProperty(
+ const wpi::Twine& key,
+ std::function<wpi::StringRef(wpi::SmallVectorImpl<char>& buf)> getter,
+ std::function<void(wpi::StringRef)> setter) override;
+
+ private:
+ struct Property {
+ Property(nt::NetworkTable& table, const wpi::Twine& key)
+ : entry(table.GetEntry(key)) {}
+
+ Property(const Property&) = delete;
+ Property& operator=(const Property&) = delete;
+
+ Property(Property&& other) noexcept
+ : entry(other.entry),
+ listener(other.listener),
+ update(std::move(other.update)),
+ createListener(std::move(other.createListener)) {
+ other.entry = nt::NetworkTableEntry();
+ other.listener = 0;
+ }
+
+ Property& operator=(Property&& other) noexcept {
+ entry = other.entry;
+ listener = other.listener;
+ other.entry = nt::NetworkTableEntry();
+ other.listener = 0;
+ update = std::move(other.update);
+ createListener = std::move(other.createListener);
+ return *this;
+ }
+
+ ~Property() { StopListener(); }
+
+ void StartListener() {
+ if (entry && listener == 0 && createListener)
+ listener = createListener(entry);
+ }
+
+ void StopListener() {
+ if (entry && listener != 0) {
+ entry.RemoveListener(listener);
+ listener = 0;
+ }
+ }
+
+ nt::NetworkTableEntry entry;
+ NT_EntryListener listener = 0;
+ std::function<void(nt::NetworkTableEntry entry, uint64_t time)> update;
+ std::function<NT_EntryListener(nt::NetworkTableEntry entry)> createListener;
+ };
+
+ std::vector<Property> m_properties;
+ std::function<void()> m_safeState;
+ std::function<void()> m_updateTable;
+ std::shared_ptr<nt::NetworkTable> m_table;
+ nt::NetworkTableEntry m_controllableEntry;
+ bool m_actuator = false;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h
new file mode 100644
index 0000000..6cf3c47
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h
@@ -0,0 +1,68 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+
+#include <wpi/StringMap.h>
+#include <wpi/StringRef.h>
+#include <wpi/deprecated.h>
+
+#include "frc/smartdashboard/SendableBuilder.h"
+#include "frc/smartdashboard/SendableChooserBase.h"
+
+namespace frc {
+
+/**
+ * The SendableChooser class is a useful tool for presenting a selection of
+ * options to the SmartDashboard.
+ *
+ * For instance, you may wish to be able to select between multiple autonomous
+ * modes. You can do this by putting every possible Command you want to run as
+ * an autonomous into a SendableChooser and then put it into the SmartDashboard
+ * to have a list of options appear on the laptop. Once autonomous starts,
+ * simply ask the SendableChooser what the selected value is.
+ *
+ * @tparam T The type of values to be stored
+ * @see SmartDashboard
+ */
+template <class T>
+class SendableChooser : public SendableChooserBase {
+ wpi::StringMap<T> m_choices;
+
+ template <class U>
+ static U _unwrap_smart_ptr(const U& value);
+
+ template <class U>
+ static U* _unwrap_smart_ptr(const std::unique_ptr<U>& value);
+
+ template <class U>
+ static std::weak_ptr<U> _unwrap_smart_ptr(const std::shared_ptr<U>& value);
+
+ public:
+ ~SendableChooser() override = default;
+
+ void AddOption(wpi::StringRef name, T object);
+ void SetDefaultOption(wpi::StringRef name, T object);
+
+ WPI_DEPRECATED("use AddOption() instead")
+ void AddObject(wpi::StringRef name, T object) { AddOption(name, object); }
+
+ WPI_DEPRECATED("use SetDefaultOption() instead")
+ void AddDefault(wpi::StringRef name, T object) {
+ SetDefaultOption(name, object);
+ }
+
+ auto GetSelected() -> decltype(_unwrap_smart_ptr(m_choices[""]));
+
+ void InitSendable(SendableBuilder& builder) override;
+};
+
+} // namespace frc
+
+#include "frc/smartdashboard/SendableChooser.inc"
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.inc b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.inc
new file mode 100644
index 0000000..42b4a65
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.inc
@@ -0,0 +1,142 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <wpi/StringRef.h>
+
+namespace frc {
+
+/**
+ * Adds the given object to the list of options.
+ *
+ * On the SmartDashboard on the desktop, the object will appear as the given
+ * name.
+ *
+ * @param name the name of the option
+ * @param object the option
+ */
+template <class T>
+void SendableChooser<T>::AddOption(wpi::StringRef name, T object) {
+ m_choices[name] = std::move(object);
+}
+
+/**
+ * Add the given object to the list of options and marks it as the default.
+ *
+ * Functionally, this is very close to AddOption() except that it will use this
+ * as the default option if none other is explicitly selected.
+ *
+ * @param name the name of the option
+ * @param object the option
+ */
+template <class T>
+void SendableChooser<T>::SetDefaultOption(wpi::StringRef name, T object) {
+ m_defaultChoice = name;
+ AddOption(name, std::move(object));
+}
+
+/**
+ * Returns a copy of the selected option (a raw pointer U* if T =
+ * std::unique_ptr<U> or a std::weak_ptr<U> if T = std::shared_ptr<U>).
+ *
+ * If there is none selected, it will return the default. If there is none
+ * selected and no default, then it will return a value-initialized instance.
+ * For integer types, this is 0. For container types like std::string, this is
+ * an empty string.
+ *
+ * @return The option selected
+ */
+template <class T>
+auto SendableChooser<T>::GetSelected()
+ -> decltype(_unwrap_smart_ptr(m_choices[""])) {
+ std::string selected = m_defaultChoice;
+ {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ if (m_haveSelected) selected = m_selected;
+ }
+ if (selected.empty()) {
+ return decltype(_unwrap_smart_ptr(m_choices[""])){};
+ } else {
+ return _unwrap_smart_ptr(m_choices[selected]);
+ }
+}
+
+template <class T>
+void SendableChooser<T>::InitSendable(SendableBuilder& builder) {
+ builder.SetSmartDashboardType("String Chooser");
+ builder.GetEntry(kInstance).SetDouble(m_instance);
+ builder.AddStringArrayProperty(kOptions,
+ [=]() {
+ std::vector<std::string> keys;
+ for (const auto& choice : m_choices) {
+ keys.push_back(choice.first());
+ }
+
+ // Unlike std::map, wpi::StringMap elements
+ // are not sorted
+ std::sort(keys.begin(), keys.end());
+
+ return keys;
+ },
+ nullptr);
+ builder.AddSmallStringProperty(
+ kDefault,
+ [=](wpi::SmallVectorImpl<char>&) -> wpi::StringRef {
+ return m_defaultChoice;
+ },
+ nullptr);
+ builder.AddSmallStringProperty(
+ kActive,
+ [=](wpi::SmallVectorImpl<char>& buf) -> wpi::StringRef {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ if (m_haveSelected) {
+ buf.assign(m_selected.begin(), m_selected.end());
+ return wpi::StringRef(buf.data(), buf.size());
+ } else {
+ return m_defaultChoice;
+ }
+ },
+ nullptr);
+ {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ m_activeEntries.emplace_back(builder.GetEntry(kActive));
+ }
+ builder.AddStringProperty(kSelected, nullptr, [=](wpi::StringRef val) {
+ std::lock_guard<wpi::mutex> lock(m_mutex);
+ m_haveSelected = true;
+ m_selected = val;
+ for (auto& entry : m_activeEntries) entry.SetString(val);
+ });
+}
+
+template <class T>
+template <class U>
+U SendableChooser<T>::_unwrap_smart_ptr(const U& value) {
+ return value;
+}
+
+template <class T>
+template <class U>
+U* SendableChooser<T>::_unwrap_smart_ptr(const std::unique_ptr<U>& value) {
+ return value.get();
+}
+
+template <class T>
+template <class U>
+std::weak_ptr<U> SendableChooser<T>::_unwrap_smart_ptr(
+ const std::shared_ptr<U>& value) {
+ return value;
+}
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooserBase.h b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooserBase.h
new file mode 100644
index 0000000..ae7908e
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooserBase.h
@@ -0,0 +1,51 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <atomic>
+#include <string>
+
+#include <networktables/NetworkTableEntry.h>
+#include <wpi/SmallVector.h>
+#include <wpi/mutex.h>
+
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+/**
+ * This class is a non-template base class for SendableChooser.
+ *
+ * It contains static, non-templated variables to avoid their duplication in the
+ * template class.
+ */
+class SendableChooserBase : public SendableBase {
+ public:
+ SendableChooserBase();
+ ~SendableChooserBase() override = default;
+
+ SendableChooserBase(SendableChooserBase&&) = default;
+ SendableChooserBase& operator=(SendableChooserBase&&) = default;
+
+ protected:
+ static constexpr const char* kDefault = "default";
+ static constexpr const char* kOptions = "options";
+ static constexpr const char* kSelected = "selected";
+ static constexpr const char* kActive = "active";
+ static constexpr const char* kInstance = ".instance";
+
+ std::string m_defaultChoice;
+ std::string m_selected;
+ bool m_haveSelected = false;
+ wpi::SmallVector<nt::NetworkTableEntry, 2> m_activeEntries;
+ wpi::mutex m_mutex;
+ int m_instance;
+ static std::atomic_int s_instances;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SmartDashboard.h b/wpilibc/src/main/native/include/frc/smartdashboard/SmartDashboard.h
new file mode 100644
index 0000000..903fb8b
--- /dev/null
+++ b/wpilibc/src/main/native/include/frc/smartdashboard/SmartDashboard.h
@@ -0,0 +1,413 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2011-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <networktables/NetworkTableValue.h>
+
+#include "frc/ErrorBase.h"
+#include "frc/smartdashboard/SendableBase.h"
+
+namespace frc {
+
+class Sendable;
+
+class SmartDashboard : public ErrorBase, public SendableBase {
+ public:
+ static void init();
+
+ /**
+ * Determines whether the given key is in this table.
+ *
+ * @param key the key to search for
+ * @return true if the table as a value assigned to the given key
+ */
+ static bool ContainsKey(wpi::StringRef key);
+
+ /**
+ * @param types bitmask of types; 0 is treated as a "don't care".
+ * @return keys currently in the table
+ */
+ static std::vector<std::string> GetKeys(int types = 0);
+
+ /**
+ * Makes a key's value persistent through program restarts.
+ *
+ * @param key the key to make persistent
+ */
+ static void SetPersistent(wpi::StringRef key);
+
+ /**
+ * Stop making a key's value persistent through program restarts.
+ * The key cannot be null.
+ *
+ * @param key the key name
+ */
+ static void ClearPersistent(wpi::StringRef key);
+
+ /**
+ * Returns whether the value is persistent through program restarts.
+ * The key cannot be null.
+ *
+ * @param key the key name
+ */
+ static bool IsPersistent(wpi::StringRef key);
+
+ /**
+ * Sets flags on the specified key in this table. The key can
+ * not be null.
+ *
+ * @param key the key name
+ * @param flags the flags to set (bitmask)
+ */
+ static void SetFlags(wpi::StringRef key, unsigned int flags);
+
+ /**
+ * Clears flags on the specified key in this table. The key can
+ * not be null.
+ *
+ * @param key the key name
+ * @param flags the flags to clear (bitmask)
+ */
+ static void ClearFlags(wpi::StringRef key, unsigned int flags);
+
+ /**
+ * Returns the flags for the specified key.
+ *
+ * @param key the key name
+ * @return the flags, or 0 if the key is not defined
+ */
+ static unsigned int GetFlags(wpi::StringRef key);
+
+ /**
+ * Deletes the specified key in this table.
+ *
+ * @param key the key name
+ */
+ static void Delete(wpi::StringRef key);
+
+ /**
+ * Maps the specified key to the specified value in this table.
+ *
+ * The value can be retrieved by calling the get method with a key that is
+ * equal to the original key.
+ *
+ * @param keyName the key
+ * @param value the value
+ */
+ static void PutData(wpi::StringRef key, Sendable* data);
+
+ /**
+ * Maps the specified key (where the key is the name of the Sendable)
+ * to the specified value in this table.
+ *
+ * The value can be retrieved by calling the get method with a key that is
+ * equal to the original key.
+ *
+ * @param value the value
+ */
+ static void PutData(Sendable* value);
+
+ /**
+ * Returns the value at the specified key.
+ *
+ * @param keyName the key
+ * @return the value
+ */
+ static Sendable* GetData(wpi::StringRef keyName);
+
+ /**
+ * Maps the specified key to the specified value in this table.
+ *
+ * The value can be retrieved by calling the get method with a key that is
+ * equal to the original key.
+ *
+ * @param keyName the key
+ * @param value the value
+ * @return False if the table key already exists with a different type
+ */
+ static bool PutBoolean(wpi::StringRef keyName, bool value);
+
+ /**
+ * Gets the current value in the table, setting it if it does not exist.
+ * @param key the key
+ * @param defaultValue the default value to set if key doesn't exist.
+ * @returns False if the table key exists with a different type
+ */
+ static bool SetDefaultBoolean(wpi::StringRef key, bool defaultValue);
+
+ /**
+ * Returns the value at the specified key.
+ *
+ * If the key is not found, returns the default value.
+ *
+ * @param keyName the key
+ * @return the value
+ */
+ static bool GetBoolean(wpi::StringRef keyName, bool defaultValue);
+
+ /**
+ * Maps the specified key to the specified value in this table.
+ *
+ * The value can be retrieved by calling the get method with a key that is
+ * equal to the original key.
+ *
+ * @param keyName the key
+ * @param value the value
+ * @return False if the table key already exists with a different type
+ */
+ static bool PutNumber(wpi::StringRef keyName, double value);
+
+ /**
+ * Gets the current value in the table, setting it if it does not exist.
+ *
+ * @param key The key.
+ * @param defaultValue The default value to set if key doesn't exist.
+ * @returns False if the table key exists with a different type
+ */
+ static bool SetDefaultNumber(wpi::StringRef key, double defaultValue);
+
+ /**
+ * Returns the value at the specified key.
+ *
+ * If the key is not found, returns the default value.
+ *
+ * @param keyName the key
+ * @return the value
+ */
+ static double GetNumber(wpi::StringRef keyName, double defaultValue);
+
+ /**
+ * Maps the specified key to the specified value in this table.
+ *
+ * The value can be retrieved by calling the get method with a key that is
+ * equal to the original key.
+ *
+ * @param keyName the key
+ * @param value the value
+ * @return False if the table key already exists with a different type
+ */
+ static bool PutString(wpi::StringRef keyName, wpi::StringRef value);
+
+ /**
+ * Gets the current value in the table, setting it if it does not exist.
+ *
+ * @param key the key
+ * @param defaultValue the default value to set if key doesn't exist.
+ * @returns False if the table key exists with a different type
+ */
+ static bool SetDefaultString(wpi::StringRef key, wpi::StringRef defaultValue);
+
+ /**
+ * Returns the value at the specified key.
+ *
+ * If the key is not found, returns the default value.
+ *
+ * @param keyName the key
+ * @return the value
+ */
+ static std::string GetString(wpi::StringRef keyName,
+ wpi::StringRef defaultValue);
+
+ /**
+ * Put a boolean array in the table.
+ *
+ * @param key the key to be assigned to
+ * @param value the value that will be assigned
+ * @return False if the table key already exists with a different type
+ *
+ * @note The array must be of int's rather than of bool's because
+ * std::vector<bool> is special-cased in C++. 0 is false, any
+ * non-zero value is true.
+ */
+ static bool PutBooleanArray(wpi::StringRef key, wpi::ArrayRef<int> value);
+
+ /**
+ * Gets the current value in the table, setting it if it does not exist.
+ *
+ * @param key the key
+ * @param defaultValue the default value to set if key doesn't exist.
+ * @returns False if the table key exists with a different type
+ */
+ static bool SetDefaultBooleanArray(wpi::StringRef key,
+ wpi::ArrayRef<int> defaultValue);
+
+ /**
+ * Returns the boolean array the key maps to.
+ *
+ * If the key does not exist or is of different type, it will return the
+ * default value.
+ *
+ * @param key The key to look up.
+ * @param defaultValue The value to be returned if no value is found.
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ *
+ * @note This makes a copy of the array. If the overhead of this is a concern,
+ * use GetValue() instead.
+ *
+ * @note The returned array is std::vector<int> instead of std::vector<bool>
+ * because std::vector<bool> is special-cased in C++. 0 is false, any
+ * non-zero value is true.
+ */
+ static std::vector<int> GetBooleanArray(wpi::StringRef key,
+ wpi::ArrayRef<int> defaultValue);
+
+ /**
+ * Put a number array in the table.
+ *
+ * @param key The key to be assigned to.
+ * @param value The value that will be assigned.
+ * @return False if the table key already exists with a different type
+ */
+ static bool PutNumberArray(wpi::StringRef key, wpi::ArrayRef<double> value);
+
+ /**
+ * Gets the current value in the table, setting it if it does not exist.
+ *
+ * @param key The key.
+ * @param defaultValue The default value to set if key doesn't exist.
+ * @returns False if the table key exists with a different type
+ */
+ static bool SetDefaultNumberArray(wpi::StringRef key,
+ wpi::ArrayRef<double> defaultValue);
+
+ /**
+ * Returns the number array the key maps to.
+ *
+ * If the key does not exist or is of different type, it will return the
+ * default value.
+ *
+ * @param key The key to look up.
+ * @param defaultValue The value to be returned if no value is found.
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ *
+ * @note This makes a copy of the array. If the overhead of this is a concern,
+ * use GetValue() instead.
+ */
+ static std::vector<double> GetNumberArray(wpi::StringRef key,
+ wpi::ArrayRef<double> defaultValue);
+
+ /**
+ * Put a string array in the table.
+ *
+ * @param key The key to be assigned to.
+ * @param value The value that will be assigned.
+ * @return False if the table key already exists with a different type
+ */
+ static bool PutStringArray(wpi::StringRef key,
+ wpi::ArrayRef<std::string> value);
+
+ /**
+ * Gets the current value in the table, setting it if it does not exist.
+ *
+ * @param key The key.
+ * @param defaultValue The default value to set if key doesn't exist.
+ * @returns False if the table key exists with a different type
+ */
+ static bool SetDefaultStringArray(wpi::StringRef key,
+ wpi::ArrayRef<std::string> defaultValue);
+
+ /**
+ * Returns the string array the key maps to.
+ *
+ * If the key does not exist or is of different type, it will return the
+ * default value.
+ *
+ * @param key The key to look up.
+ * @param defaultValue The value to be returned if no value is found.
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ *
+ * @note This makes a copy of the array. If the overhead of this is a concern,
+ * use GetValue() instead.
+ */
+ static std::vector<std::string> GetStringArray(
+ wpi::StringRef key, wpi::ArrayRef<std::string> defaultValue);
+
+ /**
+ * Put a raw value (byte array) in the table.
+ *
+ * @param key The key to be assigned to.
+ * @param value The value that will be assigned.
+ * @return False if the table key already exists with a different type
+ */
+ static bool PutRaw(wpi::StringRef key, wpi::StringRef value);
+
+ /**
+ * Gets the current value in the table, setting it if it does not exist.
+ *
+ * @param key The key.
+ * @param defaultValue The default value to set if key doesn't exist.
+ * @returns False if the table key exists with a different type
+ */
+ static bool SetDefaultRaw(wpi::StringRef key, wpi::StringRef defaultValue);
+
+ /**
+ * Returns the raw value (byte array) the key maps to.
+ *
+ * If the key does not exist or is of different type, it will return the
+ * default value.
+ *
+ * @param key The key to look up.
+ * @param defaultValue The value to be returned if no value is found.
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ *
+ * @note This makes a copy of the raw contents. If the overhead of this is a
+ * concern, use GetValue() instead.
+ */
+ static std::string GetRaw(wpi::StringRef key, wpi::StringRef defaultValue);
+
+ /**
+ * Maps the specified key to the specified complex value (such as an array) in
+ * this table.
+ *
+ * The value can be retrieved by calling the RetrieveValue method with a key
+ * that is equal to the original key.
+ *
+ * @param keyName the key
+ * @param value the value
+ * @return False if the table key already exists with a different type
+ */
+ static bool PutValue(wpi::StringRef keyName,
+ std::shared_ptr<nt::Value> value);
+
+ /**
+ * Gets the current value in the table, setting it if it does not exist.
+ *
+ * @param key the key
+ * @param defaultValue The default value to set if key doesn't exist.
+ * @returns False if the table key exists with a different type
+ */
+ static bool SetDefaultValue(wpi::StringRef key,
+ std::shared_ptr<nt::Value> defaultValue);
+
+ /**
+ * Retrieves the complex value (such as an array) in this table into the
+ * complex data object.
+ *
+ * @param keyName the key
+ * @param value the object to retrieve the value into
+ */
+ static std::shared_ptr<nt::Value> GetValue(wpi::StringRef keyName);
+
+ /**
+ * Puts all sendable data to the dashboard.
+ */
+ static void UpdateValues();
+
+ private:
+ virtual ~SmartDashboard() = default;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/main/native/include/interfaces/Accelerometer.h b/wpilibc/src/main/native/include/interfaces/Accelerometer.h
new file mode 100644
index 0000000..74b3c38
--- /dev/null
+++ b/wpilibc/src/main/native/include/interfaces/Accelerometer.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: interfaces/Accelerometer.h is deprecated; include frc/interfaces/Accelerometer.h instead"
+#else
+#warning "interfaces/Accelerometer.h is deprecated; include frc/interfaces/Accelerometer.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/interfaces/Accelerometer.h"
diff --git a/wpilibc/src/main/native/include/interfaces/Gyro.h b/wpilibc/src/main/native/include/interfaces/Gyro.h
new file mode 100644
index 0000000..f88ec5d
--- /dev/null
+++ b/wpilibc/src/main/native/include/interfaces/Gyro.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: interfaces/Gyro.h is deprecated; include frc/interfaces/Gyro.h instead"
+#else
+#warning "interfaces/Gyro.h is deprecated; include frc/interfaces/Gyro.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/interfaces/Gyro.h"
diff --git a/wpilibc/src/main/native/include/interfaces/Potentiometer.h b/wpilibc/src/main/native/include/interfaces/Potentiometer.h
new file mode 100644
index 0000000..d73d3db
--- /dev/null
+++ b/wpilibc/src/main/native/include/interfaces/Potentiometer.h
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+// clang-format off
+#ifdef _MSC_VER
+#pragma message "warning: interfaces/Potentiometer.h is deprecated; include frc/interfaces/Potentiometer.h instead"
+#else
+#warning "interfaces/Potentiometer.h is deprecated; include frc/interfaces/Potentiometer.h instead"
+#endif
+
+// clang-format on
+
+#include "frc/interfaces/Potentiometer.h"
diff --git a/wpilibc/src/test/native/c/test.c b/wpilibc/src/test/native/c/test.c
new file mode 100644
index 0000000..105e289
--- /dev/null
+++ b/wpilibc/src/test/native/c/test.c
@@ -0,0 +1,10 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 <cscore.h>
+#include <hal/HAL.h>
+#include <ntcore.h>
diff --git a/wpilibc/src/test/native/cpp/CircularBufferTest.cpp b/wpilibc/src/test/native/cpp/CircularBufferTest.cpp
new file mode 100644
index 0000000..ada4f9a
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/CircularBufferTest.cpp
@@ -0,0 +1,211 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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 "frc/circular_buffer.h" // NOLINT(build/include_order)
+
+#include <array>
+
+#include "gtest/gtest.h"
+
+using namespace frc;
+
+static const std::array<double, 10> values = {
+ {751.848, 766.366, 342.657, 234.252, 716.126, 132.344, 445.697, 22.727,
+ 421.125, 799.913}};
+
+static const std::array<double, 8> pushFrontOut = {
+ {799.913, 421.125, 22.727, 445.697, 132.344, 716.126, 234.252, 342.657}};
+
+static const std::array<double, 8> pushBackOut = {
+ {342.657, 234.252, 716.126, 132.344, 445.697, 22.727, 421.125, 799.913}};
+
+TEST(CircularBufferTest, PushFrontTest) {
+ circular_buffer<double> queue(8);
+
+ for (auto& value : values) {
+ queue.push_front(value);
+ }
+
+ for (size_t i = 0; i < pushFrontOut.size(); i++) {
+ EXPECT_EQ(pushFrontOut[i], queue[i]);
+ }
+}
+
+TEST(CircularBufferTest, PushBackTest) {
+ circular_buffer<double> queue(8);
+
+ for (auto& value : values) {
+ queue.push_back(value);
+ }
+
+ for (size_t i = 0; i < pushBackOut.size(); i++) {
+ EXPECT_EQ(pushBackOut[i], queue[i]);
+ }
+}
+
+TEST(CircularBufferTest, PushPopTest) {
+ circular_buffer<double> queue(3);
+
+ // Insert three elements into the buffer
+ queue.push_back(1.0);
+ queue.push_back(2.0);
+ queue.push_back(3.0);
+
+ EXPECT_EQ(1.0, queue[0]);
+ EXPECT_EQ(2.0, queue[1]);
+ EXPECT_EQ(3.0, queue[2]);
+
+ /*
+ * The buffer is full now, so pushing subsequent elements will overwrite the
+ * front-most elements.
+ */
+
+ queue.push_back(4.0); // Overwrite 1 with 4
+
+ // The buffer now contains 2, 3 and 4
+ EXPECT_EQ(2.0, queue[0]);
+ EXPECT_EQ(3.0, queue[1]);
+ EXPECT_EQ(4.0, queue[2]);
+
+ queue.push_back(5.0); // Overwrite 2 with 5
+
+ // The buffer now contains 3, 4 and 5
+ EXPECT_EQ(3.0, queue[0]);
+ EXPECT_EQ(4.0, queue[1]);
+ EXPECT_EQ(5.0, queue[2]);
+
+ EXPECT_EQ(5.0, queue.pop_back()); // 5 is removed
+
+ // The buffer now contains 3 and 4
+ EXPECT_EQ(3.0, queue[0]);
+ EXPECT_EQ(4.0, queue[1]);
+
+ EXPECT_EQ(3.0, queue.pop_front()); // 3 is removed
+
+ // Leaving only one element with value == 4
+ EXPECT_EQ(4.0, queue[0]);
+}
+
+TEST(CircularBufferTest, ResetTest) {
+ circular_buffer<double> queue(5);
+
+ for (size_t i = 1; i < 6; i++) {
+ queue.push_back(i);
+ }
+
+ queue.reset();
+
+ for (size_t i = 0; i < 5; i++) {
+ EXPECT_EQ(0.0, queue[i]);
+ }
+}
+
+TEST(CircularBufferTest, ResizeTest) {
+ circular_buffer<double> queue(5);
+
+ /* Buffer contains {1, 2, 3, _, _}
+ * ^ front
+ */
+ queue.push_back(1.0);
+ queue.push_back(2.0);
+ queue.push_back(3.0);
+
+ queue.resize(2);
+ EXPECT_EQ(1.0, queue[0]);
+ EXPECT_EQ(2.0, queue[1]);
+
+ queue.resize(5);
+ EXPECT_EQ(1.0, queue[0]);
+ EXPECT_EQ(2.0, queue[1]);
+
+ queue.reset();
+
+ /* Buffer contains {_, 1, 2, 3, _}
+ * ^ front
+ */
+ queue.push_back(0.0);
+ queue.push_back(1.0);
+ queue.push_back(2.0);
+ queue.push_back(3.0);
+ queue.pop_front();
+
+ queue.resize(2);
+ EXPECT_EQ(1.0, queue[0]);
+ EXPECT_EQ(2.0, queue[1]);
+
+ queue.resize(5);
+ EXPECT_EQ(1.0, queue[0]);
+ EXPECT_EQ(2.0, queue[1]);
+
+ queue.reset();
+
+ /* Buffer contains {_, _, 1, 2, 3}
+ * ^ front
+ */
+ queue.push_back(0.0);
+ queue.push_back(0.0);
+ queue.push_back(1.0);
+ queue.push_back(2.0);
+ queue.push_back(3.0);
+ queue.pop_front();
+ queue.pop_front();
+
+ queue.resize(2);
+ EXPECT_EQ(1.0, queue[0]);
+ EXPECT_EQ(2.0, queue[1]);
+
+ queue.resize(5);
+ EXPECT_EQ(1.0, queue[0]);
+ EXPECT_EQ(2.0, queue[1]);
+
+ queue.reset();
+
+ /* Buffer contains {3, _, _, 1, 2}
+ * ^ front
+ */
+ queue.push_back(3.0);
+ queue.push_front(2.0);
+ queue.push_front(1.0);
+
+ queue.resize(2);
+ EXPECT_EQ(1.0, queue[0]);
+ EXPECT_EQ(2.0, queue[1]);
+
+ queue.resize(5);
+ EXPECT_EQ(1.0, queue[0]);
+ EXPECT_EQ(2.0, queue[1]);
+
+ queue.reset();
+
+ /* Buffer contains {2, 3, _, _, 1}
+ * ^ front
+ */
+ queue.push_back(2.0);
+ queue.push_back(3.0);
+ queue.push_front(1.0);
+
+ queue.resize(2);
+ EXPECT_EQ(1.0, queue[0]);
+ EXPECT_EQ(2.0, queue[1]);
+
+ queue.resize(5);
+ EXPECT_EQ(1.0, queue[0]);
+ EXPECT_EQ(2.0, queue[1]);
+
+ // Test push_back() after resize
+ queue.push_back(3.0);
+ EXPECT_EQ(1.0, queue[0]);
+ EXPECT_EQ(2.0, queue[1]);
+ EXPECT_EQ(3.0, queue[2]);
+
+ // Test push_front() after resize
+ queue.push_front(4.0);
+ EXPECT_EQ(4.0, queue[0]);
+ EXPECT_EQ(1.0, queue[1]);
+ EXPECT_EQ(2.0, queue[2]);
+ EXPECT_EQ(3.0, queue[3]);
+}
diff --git a/wpilibc/src/test/native/cpp/FilterNoiseTest.cpp b/wpilibc/src/test/native/cpp/FilterNoiseTest.cpp
new file mode 100644
index 0000000..ea14f32
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/FilterNoiseTest.cpp
@@ -0,0 +1,137 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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 "frc/filters/LinearDigitalFilter.h" // NOLINT(build/include_order)
+
+#include <cmath>
+#include <functional>
+#include <memory>
+#include <random>
+#include <thread>
+
+#include "frc/Base.h"
+#include "gtest/gtest.h"
+
+/* Filter constants */
+static constexpr double kFilterStep = 0.005;
+static constexpr double kFilterTime = 2.0;
+static constexpr double kSinglePoleIIRTimeConstant = 0.015915;
+static constexpr double kSinglePoleIIRExpectedOutput = -3.2172003;
+static constexpr double kHighPassTimeConstant = 0.006631;
+static constexpr double kHighPassExpectedOutput = 10.074717;
+static constexpr int32_t kMovAvgTaps = 6;
+static constexpr double kMovAvgExpectedOutput = -10.191644;
+static constexpr double kPi = 3.14159265358979323846;
+
+using namespace frc;
+
+enum FilterNoiseTestType { TEST_SINGLE_POLE_IIR, TEST_MOVAVG };
+
+std::ostream& operator<<(std::ostream& os, const FilterNoiseTestType& type) {
+ switch (type) {
+ case TEST_SINGLE_POLE_IIR:
+ os << "LinearDigitalFilter SinglePoleIIR";
+ break;
+ case TEST_MOVAVG:
+ os << "LinearDigitalFilter MovingAverage";
+ break;
+ }
+
+ return os;
+}
+
+constexpr double kStdDev = 10.0;
+
+/**
+ * Adds Gaussian white noise to a function returning data. The noise will have
+ * the standard deviation provided in the constructor.
+ */
+class NoiseGenerator : public PIDSource {
+ public:
+ NoiseGenerator(double (*dataFunc)(double), double stdDev)
+ : m_distr(0.0, stdDev) {
+ m_dataFunc = dataFunc;
+ }
+
+ void SetPIDSourceType(PIDSourceType pidSource) override {}
+
+ double Get() { return m_dataFunc(m_count) + m_noise; }
+
+ double PIDGet() override {
+ m_noise = m_distr(m_gen);
+ m_count += kFilterStep;
+ return m_dataFunc(m_count) + m_noise;
+ }
+
+ void Reset() { m_count = -kFilterStep; }
+
+ private:
+ std::function<double(double)> m_dataFunc;
+ double m_noise = 0.0;
+
+ // Make sure first call to PIDGet() uses m_count == 0
+ double m_count = -kFilterStep;
+
+ std::random_device m_rd;
+ std::mt19937 m_gen{m_rd()};
+ std::normal_distribution<double> m_distr;
+};
+
+/**
+ * A fixture that includes a noise generator wrapped in a filter
+ */
+class FilterNoiseTest : public testing::TestWithParam<FilterNoiseTestType> {
+ protected:
+ std::unique_ptr<PIDSource> m_filter;
+ std::shared_ptr<NoiseGenerator> m_noise;
+
+ static double GetData(double t) { return 100.0 * std::sin(2.0 * kPi * t); }
+
+ void SetUp() override {
+ m_noise = std::make_shared<NoiseGenerator>(GetData, kStdDev);
+
+ switch (GetParam()) {
+ case TEST_SINGLE_POLE_IIR: {
+ m_filter = std::make_unique<LinearDigitalFilter>(
+ LinearDigitalFilter::SinglePoleIIR(
+ m_noise, kSinglePoleIIRTimeConstant, kFilterStep));
+ break;
+ }
+
+ case TEST_MOVAVG: {
+ m_filter = std::make_unique<LinearDigitalFilter>(
+ LinearDigitalFilter::MovingAverage(m_noise, kMovAvgTaps));
+ break;
+ }
+ }
+ }
+};
+
+/**
+ * Test if the filter reduces the noise produced by a signal generator
+ */
+TEST_P(FilterNoiseTest, NoiseReduce) {
+ double theoryData = 0.0;
+ double noiseGenError = 0.0;
+ double filterError = 0.0;
+
+ m_noise->Reset();
+ for (double t = 0; t < kFilterTime; t += kFilterStep) {
+ theoryData = GetData(t);
+ filterError += std::abs(m_filter->PIDGet() - theoryData);
+ noiseGenError += std::abs(m_noise->Get() - theoryData);
+ }
+
+ RecordProperty("FilterError", filterError);
+
+ // The filter should have produced values closer to the theory
+ EXPECT_GT(noiseGenError, filterError)
+ << "Filter should have reduced noise accumulation but failed";
+}
+
+INSTANTIATE_TEST_CASE_P(Test, FilterNoiseTest,
+ testing::Values(TEST_SINGLE_POLE_IIR, TEST_MOVAVG), );
diff --git a/wpilibc/src/test/native/cpp/FilterOutputTest.cpp b/wpilibc/src/test/native/cpp/FilterOutputTest.cpp
new file mode 100644
index 0000000..ec71760
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/FilterOutputTest.cpp
@@ -0,0 +1,157 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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 "frc/filters/LinearDigitalFilter.h" // NOLINT(build/include_order)
+
+#include <cmath>
+#include <functional>
+#include <memory>
+#include <random>
+#include <thread>
+
+#include "frc/Base.h"
+#include "gtest/gtest.h"
+
+/* Filter constants */
+static constexpr double kFilterStep = 0.005;
+static constexpr double kFilterTime = 2.0;
+static constexpr double kSinglePoleIIRTimeConstant = 0.015915;
+static constexpr double kSinglePoleIIRExpectedOutput = -3.2172003;
+static constexpr double kHighPassTimeConstant = 0.006631;
+static constexpr double kHighPassExpectedOutput = 10.074717;
+static constexpr int32_t kMovAvgTaps = 6;
+static constexpr double kMovAvgExpectedOutput = -10.191644;
+static constexpr double kPi = 3.14159265358979323846;
+
+using namespace frc;
+
+enum FilterOutputTestType {
+ TEST_SINGLE_POLE_IIR,
+ TEST_HIGH_PASS,
+ TEST_MOVAVG,
+ TEST_PULSE
+};
+
+std::ostream& operator<<(std::ostream& os, const FilterOutputTestType& type) {
+ switch (type) {
+ case TEST_SINGLE_POLE_IIR:
+ os << "LinearDigitalFilter SinglePoleIIR";
+ break;
+ case TEST_HIGH_PASS:
+ os << "LinearDigitalFilter HighPass";
+ break;
+ case TEST_MOVAVG:
+ os << "LinearDigitalFilter MovingAverage";
+ break;
+ case TEST_PULSE:
+ os << "LinearDigitalFilter Pulse";
+ break;
+ }
+
+ return os;
+}
+
+class DataWrapper : public PIDSource {
+ public:
+ explicit DataWrapper(double (*dataFunc)(double)) { m_dataFunc = dataFunc; }
+
+ virtual void SetPIDSourceType(PIDSourceType pidSource) {}
+
+ virtual double PIDGet() {
+ m_count += kFilterStep;
+ return m_dataFunc(m_count);
+ }
+
+ void Reset() { m_count = -kFilterStep; }
+
+ private:
+ std::function<double(double)> m_dataFunc;
+
+ // Make sure first call to PIDGet() uses m_count == 0
+ double m_count = -kFilterStep;
+};
+
+/**
+ * A fixture that includes a consistent data source wrapped in a filter
+ */
+class FilterOutputTest : public testing::TestWithParam<FilterOutputTestType> {
+ protected:
+ std::unique_ptr<PIDSource> m_filter;
+ std::shared_ptr<DataWrapper> m_data;
+ double m_expectedOutput = 0.0;
+
+ static double GetData(double t) {
+ return 100.0 * std::sin(2.0 * kPi * t) + 20.0 * std::cos(50.0 * kPi * t);
+ }
+
+ static double GetPulseData(double t) {
+ if (std::abs(t - 1.0) < 0.001) {
+ return 1.0;
+ } else {
+ return 0.0;
+ }
+ }
+
+ void SetUp() override {
+ switch (GetParam()) {
+ case TEST_SINGLE_POLE_IIR: {
+ m_data = std::make_shared<DataWrapper>(GetData);
+ m_filter = std::make_unique<LinearDigitalFilter>(
+ LinearDigitalFilter::SinglePoleIIR(
+ m_data, kSinglePoleIIRTimeConstant, kFilterStep));
+ m_expectedOutput = kSinglePoleIIRExpectedOutput;
+ break;
+ }
+
+ case TEST_HIGH_PASS: {
+ m_data = std::make_shared<DataWrapper>(GetData);
+ m_filter =
+ std::make_unique<LinearDigitalFilter>(LinearDigitalFilter::HighPass(
+ m_data, kHighPassTimeConstant, kFilterStep));
+ m_expectedOutput = kHighPassExpectedOutput;
+ break;
+ }
+
+ case TEST_MOVAVG: {
+ m_data = std::make_shared<DataWrapper>(GetData);
+ m_filter = std::make_unique<LinearDigitalFilter>(
+ LinearDigitalFilter::MovingAverage(m_data, kMovAvgTaps));
+ m_expectedOutput = kMovAvgExpectedOutput;
+ break;
+ }
+
+ case TEST_PULSE: {
+ m_data = std::make_shared<DataWrapper>(GetPulseData);
+ m_filter = std::make_unique<LinearDigitalFilter>(
+ LinearDigitalFilter::MovingAverage(m_data, kMovAvgTaps));
+ m_expectedOutput = 0.0;
+ break;
+ }
+ }
+ }
+};
+
+/**
+ * Test if the linear digital filters produce consistent output
+ */
+TEST_P(FilterOutputTest, FilterOutput) {
+ m_data->Reset();
+
+ double filterOutput = 0.0;
+ for (double t = 0.0; t < kFilterTime; t += kFilterStep) {
+ filterOutput = m_filter->PIDGet();
+ }
+
+ RecordProperty("FilterOutput", filterOutput);
+
+ EXPECT_FLOAT_EQ(m_expectedOutput, filterOutput)
+ << "Filter output didn't match expected value";
+}
+
+INSTANTIATE_TEST_CASE_P(Test, FilterOutputTest,
+ testing::Values(TEST_SINGLE_POLE_IIR, TEST_HIGH_PASS,
+ TEST_MOVAVG, TEST_PULSE), );
diff --git a/wpilibc/src/test/native/cpp/MockSpeedController.cpp b/wpilibc/src/test/native/cpp/MockSpeedController.cpp
new file mode 100644
index 0000000..875fec1
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/MockSpeedController.cpp
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "MockSpeedController.h"
+
+using namespace frc;
+
+void MockSpeedController::Set(double speed) {
+ m_speed = m_isInverted ? -speed : speed;
+}
+
+double MockSpeedController::Get() const { return m_speed; }
+
+void MockSpeedController::SetInverted(bool isInverted) {
+ m_isInverted = isInverted;
+}
+
+bool MockSpeedController::GetInverted() const { return m_isInverted; }
+
+void MockSpeedController::Disable() { m_speed = 0; }
+
+void MockSpeedController::StopMotor() { Disable(); }
+
+void MockSpeedController::PIDWrite(double output) { Set(output); }
diff --git a/wpilibc/src/test/native/cpp/RobotDriveTest.cpp b/wpilibc/src/test/native/cpp/RobotDriveTest.cpp
new file mode 100644
index 0000000..464a707
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/RobotDriveTest.cpp
@@ -0,0 +1,190 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. 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 "MockSpeedController.h"
+#include "frc/RobotDrive.h"
+#include "frc/drive/DifferentialDrive.h"
+#include "frc/drive/MecanumDrive.h"
+#include "gtest/gtest.h"
+
+using namespace frc;
+
+class RobotDriveTest : public testing::Test {
+ protected:
+ MockSpeedController m_rdFrontLeft;
+ MockSpeedController m_rdRearLeft;
+ MockSpeedController m_rdFrontRight;
+ MockSpeedController m_rdRearRight;
+ MockSpeedController m_frontLeft;
+ MockSpeedController m_rearLeft;
+ MockSpeedController m_frontRight;
+ MockSpeedController m_rearRight;
+ frc::RobotDrive m_robotDrive{m_rdFrontLeft, m_rdRearLeft, m_rdFrontRight,
+ m_rdRearRight};
+ frc::DifferentialDrive m_differentialDrive{m_frontLeft, m_frontRight};
+ frc::MecanumDrive m_mecanumDrive{m_frontLeft, m_rearLeft, m_frontRight,
+ m_rearRight};
+
+ double m_testJoystickValues[9] = {-1.0, -0.9, -0.5, -0.01, 0.0,
+ 0.01, 0.5, 0.9, 1.0};
+ double m_testGyroValues[19] = {0, 45, 90, 135, 180, 225, 270,
+ 305, 360, 540, -45, -90, -135, -180,
+ -225, -270, -305, -360, -540};
+};
+
+TEST_F(RobotDriveTest, TankDrive) {
+ int joystickSize = sizeof(m_testJoystickValues) / sizeof(double);
+ double leftJoystick, rightJoystick;
+ m_differentialDrive.SetDeadband(0.0);
+ m_differentialDrive.SetSafetyEnabled(false);
+ m_mecanumDrive.SetSafetyEnabled(false);
+ m_robotDrive.SetSafetyEnabled(false);
+ for (int i = 0; i < joystickSize; i++) {
+ for (int j = 0; j < joystickSize; j++) {
+ leftJoystick = m_testJoystickValues[i];
+ rightJoystick = m_testJoystickValues[j];
+ m_robotDrive.TankDrive(leftJoystick, rightJoystick, false);
+ m_differentialDrive.TankDrive(leftJoystick, rightJoystick, false);
+ ASSERT_NEAR(m_rdFrontLeft.Get(), m_frontLeft.Get(), 0.01);
+ ASSERT_NEAR(m_rdFrontRight.Get(), m_frontRight.Get(), 0.01);
+ }
+ }
+}
+
+TEST_F(RobotDriveTest, TankDriveSquared) {
+ int joystickSize = sizeof(m_testJoystickValues) / sizeof(double);
+ double leftJoystick, rightJoystick;
+ m_differentialDrive.SetDeadband(0.0);
+ m_differentialDrive.SetSafetyEnabled(false);
+ m_mecanumDrive.SetSafetyEnabled(false);
+ m_robotDrive.SetSafetyEnabled(false);
+ for (int i = 0; i < joystickSize; i++) {
+ for (int j = 0; j < joystickSize; j++) {
+ leftJoystick = m_testJoystickValues[i];
+ rightJoystick = m_testJoystickValues[j];
+ m_robotDrive.TankDrive(leftJoystick, rightJoystick, true);
+ m_differentialDrive.TankDrive(leftJoystick, rightJoystick, true);
+ ASSERT_NEAR(m_rdFrontLeft.Get(), m_frontLeft.Get(), 0.01);
+ ASSERT_NEAR(m_rdFrontRight.Get(), m_frontRight.Get(), 0.01);
+ }
+ }
+}
+
+TEST_F(RobotDriveTest, ArcadeDriveSquared) {
+ int joystickSize = sizeof(m_testJoystickValues) / sizeof(double);
+ double moveJoystick, rotateJoystick;
+ m_differentialDrive.SetDeadband(0.0);
+ m_differentialDrive.SetSafetyEnabled(false);
+ m_mecanumDrive.SetSafetyEnabled(false);
+ m_robotDrive.SetSafetyEnabled(false);
+ for (int i = 0; i < joystickSize; i++) {
+ for (int j = 0; j < joystickSize; j++) {
+ moveJoystick = m_testJoystickValues[i];
+ rotateJoystick = m_testJoystickValues[j];
+ m_robotDrive.ArcadeDrive(moveJoystick, rotateJoystick, true);
+ m_differentialDrive.ArcadeDrive(moveJoystick, -rotateJoystick, true);
+ ASSERT_NEAR(m_rdFrontLeft.Get(), m_frontLeft.Get(), 0.01);
+ ASSERT_NEAR(m_rdFrontRight.Get(), m_frontRight.Get(), 0.01);
+ }
+ }
+}
+
+TEST_F(RobotDriveTest, ArcadeDrive) {
+ int joystickSize = sizeof(m_testJoystickValues) / sizeof(double);
+ double moveJoystick, rotateJoystick;
+ m_differentialDrive.SetDeadband(0.0);
+ m_differentialDrive.SetSafetyEnabled(false);
+ m_mecanumDrive.SetSafetyEnabled(false);
+ m_robotDrive.SetSafetyEnabled(false);
+ for (int i = 0; i < joystickSize; i++) {
+ for (int j = 0; j < joystickSize; j++) {
+ moveJoystick = m_testJoystickValues[i];
+ rotateJoystick = m_testJoystickValues[j];
+ m_robotDrive.ArcadeDrive(moveJoystick, rotateJoystick, false);
+ m_differentialDrive.ArcadeDrive(moveJoystick, -rotateJoystick, false);
+ ASSERT_NEAR(m_rdFrontLeft.Get(), m_frontLeft.Get(), 0.01);
+ ASSERT_NEAR(m_rdFrontRight.Get(), m_frontRight.Get(), 0.01);
+ }
+ }
+}
+
+TEST_F(RobotDriveTest, MecanumCartesian) {
+ int joystickSize = sizeof(m_testJoystickValues) / sizeof(double);
+ int gyroSize = sizeof(m_testGyroValues) / sizeof(double);
+ double xJoystick, yJoystick, rotateJoystick, gyroValue;
+ m_mecanumDrive.SetDeadband(0.0);
+ m_mecanumDrive.SetSafetyEnabled(false);
+ m_differentialDrive.SetSafetyEnabled(false);
+ m_robotDrive.SetSafetyEnabled(false);
+ for (int i = 0; i < joystickSize; i++) {
+ for (int j = 0; j < joystickSize; j++) {
+ for (int k = 0; k < joystickSize; k++) {
+ for (int l = 0; l < gyroSize; l++) {
+ xJoystick = m_testJoystickValues[i];
+ yJoystick = m_testJoystickValues[j];
+ rotateJoystick = m_testJoystickValues[k];
+ gyroValue = m_testGyroValues[l];
+ m_robotDrive.MecanumDrive_Cartesian(xJoystick, yJoystick,
+ rotateJoystick, gyroValue);
+ m_mecanumDrive.DriveCartesian(xJoystick, -yJoystick, rotateJoystick,
+ -gyroValue);
+ ASSERT_NEAR(m_rdFrontLeft.Get(), m_frontLeft.Get(), 0.01)
+ << "X: " << xJoystick << " Y: " << yJoystick
+ << " Rotate: " << rotateJoystick << " Gyro: " << gyroValue;
+ ASSERT_NEAR(m_rdFrontRight.Get(), -m_frontRight.Get(), 0.01)
+ << "X: " << xJoystick << " Y: " << yJoystick
+ << " Rotate: " << rotateJoystick << " Gyro: " << gyroValue;
+ ASSERT_NEAR(m_rdRearLeft.Get(), m_rearLeft.Get(), 0.01)
+ << "X: " << xJoystick << " Y: " << yJoystick
+ << " Rotate: " << rotateJoystick << " Gyro: " << gyroValue;
+ ASSERT_NEAR(m_rdRearRight.Get(), -m_rearRight.Get(), 0.01)
+ << "X: " << xJoystick << " Y: " << yJoystick
+ << " Rotate: " << rotateJoystick << " Gyro: " << gyroValue;
+ }
+ }
+ }
+ }
+}
+
+TEST_F(RobotDriveTest, MecanumPolar) {
+ int joystickSize = sizeof(m_testJoystickValues) / sizeof(double);
+ int gyroSize = sizeof(m_testGyroValues) / sizeof(double);
+ double magnitudeJoystick, directionJoystick, rotateJoystick;
+ m_mecanumDrive.SetDeadband(0.0);
+ m_mecanumDrive.SetSafetyEnabled(false);
+ m_differentialDrive.SetSafetyEnabled(false);
+ m_robotDrive.SetSafetyEnabled(false);
+ for (int i = 0; i < joystickSize; i++) {
+ for (int j = 0; j < gyroSize; j++) {
+ for (int k = 0; k < joystickSize; k++) {
+ magnitudeJoystick = m_testJoystickValues[i];
+ directionJoystick = m_testGyroValues[j];
+ rotateJoystick = m_testJoystickValues[k];
+ m_robotDrive.MecanumDrive_Polar(magnitudeJoystick, directionJoystick,
+ rotateJoystick);
+ m_mecanumDrive.DrivePolar(magnitudeJoystick, directionJoystick,
+ rotateJoystick);
+ ASSERT_NEAR(m_rdFrontLeft.Get(), m_frontLeft.Get(), 0.01)
+ << "Magnitude: " << magnitudeJoystick
+ << " Direction: " << directionJoystick
+ << " Rotate: " << rotateJoystick;
+ ASSERT_NEAR(m_rdFrontRight.Get(), -m_frontRight.Get(), 0.01)
+ << "Magnitude: " << magnitudeJoystick
+ << " Direction: " << directionJoystick
+ << " Rotate: " << rotateJoystick;
+ ASSERT_NEAR(m_rdRearLeft.Get(), m_rearLeft.Get(), 0.01)
+ << "Magnitude: " << magnitudeJoystick
+ << " Direction: " << directionJoystick
+ << " Rotate: " << rotateJoystick;
+ ASSERT_NEAR(m_rdRearRight.Get(), -m_rearRight.Get(), 0.01)
+ << "Magnitude: " << magnitudeJoystick
+ << " Direction: " << directionJoystick
+ << " Rotate: " << rotateJoystick;
+ }
+ }
+ }
+}
diff --git a/wpilibc/src/test/native/cpp/SpeedControllerGroupTest.cpp b/wpilibc/src/test/native/cpp/SpeedControllerGroupTest.cpp
new file mode 100644
index 0000000..a6f5028
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/SpeedControllerGroupTest.cpp
@@ -0,0 +1,136 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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 "frc/SpeedControllerGroup.h" // NOLINT(build/include_order)
+
+#include <memory>
+#include <vector>
+
+#include "MockSpeedController.h"
+#include "gtest/gtest.h"
+
+using namespace frc;
+
+enum SpeedControllerGroupTestType { TEST_ONE, TEST_TWO, TEST_THREE };
+
+std::ostream& operator<<(std::ostream& os,
+ const SpeedControllerGroupTestType& type) {
+ switch (type) {
+ case TEST_ONE:
+ os << "SpeedControllerGroup with one speed controller";
+ break;
+ case TEST_TWO:
+ os << "SpeedControllerGroup with two speed controllers";
+ break;
+ case TEST_THREE:
+ os << "SpeedControllerGroup with three speed controllers";
+ break;
+ }
+
+ return os;
+}
+
+/**
+ * A fixture used for SpeedControllerGroup testing.
+ */
+class SpeedControllerGroupTest
+ : public testing::TestWithParam<SpeedControllerGroupTestType> {
+ protected:
+ std::vector<MockSpeedController> m_speedControllers;
+ std::unique_ptr<SpeedControllerGroup> m_group;
+
+ void SetUp() override {
+ switch (GetParam()) {
+ case TEST_ONE: {
+ m_speedControllers.emplace_back();
+ m_group = std::make_unique<SpeedControllerGroup>(m_speedControllers[0]);
+ break;
+ }
+
+ case TEST_TWO: {
+ m_speedControllers.emplace_back();
+ m_speedControllers.emplace_back();
+ m_group = std::make_unique<SpeedControllerGroup>(m_speedControllers[0],
+ m_speedControllers[1]);
+ break;
+ }
+
+ case TEST_THREE: {
+ m_speedControllers.emplace_back();
+ m_speedControllers.emplace_back();
+ m_speedControllers.emplace_back();
+ m_group = std::make_unique<SpeedControllerGroup>(m_speedControllers[0],
+ m_speedControllers[1],
+ m_speedControllers[2]);
+ break;
+ }
+ }
+ }
+};
+
+TEST_P(SpeedControllerGroupTest, Set) {
+ m_group->Set(1.0);
+
+ for (auto& speedController : m_speedControllers) {
+ EXPECT_FLOAT_EQ(speedController.Get(), 1.0);
+ }
+}
+
+TEST_P(SpeedControllerGroupTest, GetInverted) {
+ m_group->SetInverted(true);
+
+ EXPECT_TRUE(m_group->GetInverted());
+}
+
+TEST_P(SpeedControllerGroupTest, SetInvertedDoesNotModifySpeedControllers) {
+ for (auto& speedController : m_speedControllers) {
+ speedController.SetInverted(false);
+ }
+ m_group->SetInverted(true);
+
+ for (auto& speedController : m_speedControllers) {
+ EXPECT_EQ(speedController.GetInverted(), false);
+ }
+}
+
+TEST_P(SpeedControllerGroupTest, SetInvertedDoesInvert) {
+ m_group->SetInverted(true);
+ m_group->Set(1.0);
+
+ for (auto& speedController : m_speedControllers) {
+ EXPECT_FLOAT_EQ(speedController.Get(), -1.0);
+ }
+}
+
+TEST_P(SpeedControllerGroupTest, Disable) {
+ m_group->Set(1.0);
+ m_group->Disable();
+
+ for (auto& speedController : m_speedControllers) {
+ EXPECT_FLOAT_EQ(speedController.Get(), 0.0);
+ }
+}
+
+TEST_P(SpeedControllerGroupTest, StopMotor) {
+ m_group->Set(1.0);
+ m_group->StopMotor();
+
+ for (auto& speedController : m_speedControllers) {
+ EXPECT_FLOAT_EQ(speedController.Get(), 0.0);
+ }
+}
+
+TEST_P(SpeedControllerGroupTest, PIDWrite) {
+ m_group->PIDWrite(1.0);
+
+ for (auto& speedController : m_speedControllers) {
+ EXPECT_FLOAT_EQ(speedController.Get(), 1.0);
+ }
+}
+
+INSTANTIATE_TEST_CASE_P(Test, SpeedControllerGroupTest,
+ testing::Values(TEST_ONE, TEST_TWO, TEST_THREE), );
diff --git a/wpilibc/src/test/native/cpp/WatchdogTest.cpp b/wpilibc/src/test/native/cpp/WatchdogTest.cpp
new file mode 100644
index 0000000..141c72e
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/WatchdogTest.cpp
@@ -0,0 +1,142 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/Watchdog.h" // NOLINT(build/include_order)
+
+#include <stdint.h>
+
+#include <thread>
+
+#include <wpi/raw_ostream.h>
+
+#include "gtest/gtest.h"
+
+using namespace frc;
+
+TEST(WatchdogTest, EnableDisable) {
+ uint32_t watchdogCounter = 0;
+
+ Watchdog watchdog(0.4, [&] { watchdogCounter++; });
+
+ wpi::outs() << "Run 1\n";
+ watchdog.Enable();
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ watchdog.Disable();
+
+ EXPECT_EQ(0u, watchdogCounter) << "Watchdog triggered early";
+
+ wpi::outs() << "Run 2\n";
+ watchdogCounter = 0;
+ watchdog.Enable();
+ std::this_thread::sleep_for(std::chrono::milliseconds(600));
+ watchdog.Disable();
+
+ EXPECT_EQ(1u, watchdogCounter)
+ << "Watchdog either didn't trigger or triggered more than once";
+
+ wpi::outs() << "Run 3\n";
+ watchdogCounter = 0;
+ watchdog.Enable();
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+ watchdog.Disable();
+
+ EXPECT_EQ(1u, watchdogCounter)
+ << "Watchdog either didn't trigger or triggered more than once";
+}
+
+TEST(WatchdogTest, Reset) {
+ uint32_t watchdogCounter = 0;
+
+ Watchdog watchdog(0.4, [&] { watchdogCounter++; });
+
+ watchdog.Enable();
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ watchdog.Reset();
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ watchdog.Disable();
+
+ EXPECT_EQ(0u, watchdogCounter) << "Watchdog triggered early";
+}
+
+TEST(WatchdogTest, SetTimeout) {
+ uint32_t watchdogCounter = 0;
+
+ Watchdog watchdog(1.0, [&] { watchdogCounter++; });
+
+ watchdog.Enable();
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ watchdog.SetTimeout(0.2);
+
+ EXPECT_EQ(0.2, watchdog.GetTimeout());
+ EXPECT_EQ(0u, watchdogCounter) << "Watchdog triggered early";
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(300));
+ watchdog.Disable();
+
+ EXPECT_EQ(1u, watchdogCounter)
+ << "Watchdog either didn't trigger or triggered more than once";
+}
+
+TEST(WatchdogTest, IsExpired) {
+ Watchdog watchdog(0.2, [] {});
+ watchdog.Enable();
+
+ EXPECT_FALSE(watchdog.IsExpired());
+ std::this_thread::sleep_for(std::chrono::milliseconds(300));
+ EXPECT_TRUE(watchdog.IsExpired());
+}
+
+TEST(WatchdogTest, Epochs) {
+ uint32_t watchdogCounter = 0;
+
+ Watchdog watchdog(0.4, [&] { watchdogCounter++; });
+
+ wpi::outs() << "Run 1\n";
+ watchdog.Enable();
+ watchdog.AddEpoch("Epoch 1");
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ watchdog.AddEpoch("Epoch 2");
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ watchdog.AddEpoch("Epoch 3");
+ watchdog.Disable();
+
+ EXPECT_EQ(0u, watchdogCounter) << "Watchdog triggered early";
+
+ wpi::outs() << "Run 2\n";
+ watchdog.Enable();
+ watchdog.AddEpoch("Epoch 1");
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ watchdog.Reset();
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ watchdog.AddEpoch("Epoch 2");
+ watchdog.Disable();
+
+ EXPECT_EQ(0u, watchdogCounter) << "Watchdog triggered early";
+}
+
+TEST(WatchdogTest, MultiWatchdog) {
+ uint32_t watchdogCounter1 = 0;
+ uint32_t watchdogCounter2 = 0;
+
+ Watchdog watchdog1(0.2, [&] { watchdogCounter1++; });
+ Watchdog watchdog2(0.6, [&] { watchdogCounter2++; });
+
+ watchdog2.Enable();
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ EXPECT_EQ(0u, watchdogCounter1) << "Watchdog triggered early";
+ EXPECT_EQ(0u, watchdogCounter2) << "Watchdog triggered early";
+
+ // Sleep enough such that only the watchdog enabled later times out first
+ watchdog1.Enable();
+ std::this_thread::sleep_for(std::chrono::milliseconds(300));
+ watchdog1.Disable();
+ watchdog2.Disable();
+
+ EXPECT_EQ(1u, watchdogCounter1)
+ << "Watchdog either didn't trigger or triggered more than once";
+ EXPECT_EQ(0u, watchdogCounter2) << "Watchdog triggered early";
+}
diff --git a/wpilibc/src/test/native/cpp/main.cpp b/wpilibc/src/test/native/cpp/main.cpp
new file mode 100644
index 0000000..0e00efa
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/main.cpp
@@ -0,0 +1,17 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. 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 <hal/HAL.h>
+
+#include "gtest/gtest.h"
+
+int main(int argc, char** argv) {
+ HAL_Initialize(500, 0);
+ ::testing::InitGoogleTest(&argc, argv);
+ int ret = RUN_ALL_TESTS();
+ return ret;
+}
diff --git a/wpilibc/src/test/native/cpp/shuffleboard/MockActuatorSendable.cpp b/wpilibc/src/test/native/cpp/shuffleboard/MockActuatorSendable.cpp
new file mode 100644
index 0000000..3c9e411
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/shuffleboard/MockActuatorSendable.cpp
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "shuffleboard/MockActuatorSendable.h"
+
+using namespace frc;
+
+MockActuatorSendable::MockActuatorSendable(wpi::StringRef name)
+ : SendableBase(false) {
+ SetName(name);
+}
+
+void MockActuatorSendable::InitSendable(SendableBuilder& builder) {
+ builder.SetActuator(true);
+}
diff --git a/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardInstanceTest.cpp b/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardInstanceTest.cpp
new file mode 100644
index 0000000..ae21526
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardInstanceTest.cpp
@@ -0,0 +1,105 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/ShuffleboardInstance.h" // NOLINT(build/include_order)
+
+#include <memory>
+#include <string>
+
+#include <networktables/NetworkTableEntry.h>
+#include <networktables/NetworkTableInstance.h>
+
+#include "frc/shuffleboard/ShuffleboardInstance.h"
+#include "gtest/gtest.h"
+#include "shuffleboard/MockActuatorSendable.h"
+
+using namespace frc;
+
+class ShuffleboardInstanceTest : public testing::Test {
+ void SetUp() override {
+ m_ntInstance = nt::NetworkTableInstance::Create();
+ m_shuffleboardInstance =
+ std::make_unique<detail::ShuffleboardInstance>(m_ntInstance);
+ }
+
+ protected:
+ nt::NetworkTableInstance m_ntInstance;
+ std::unique_ptr<detail::ShuffleboardInstance> m_shuffleboardInstance;
+};
+
+TEST_F(ShuffleboardInstanceTest, PathFluent) {
+ auto entry = m_shuffleboardInstance->GetTab("Tab Title")
+ .GetLayout("List Layout", "List")
+ .Add("Data", "string")
+ .WithWidget("Text View")
+ .GetEntry();
+
+ EXPECT_EQ("string", entry.GetString("")) << "Wrong entry value";
+ EXPECT_EQ("/Shuffleboard/Tab Title/List Layout/Data", entry.GetName())
+ << "Entry path generated incorrectly";
+}
+
+TEST_F(ShuffleboardInstanceTest, NestedLayoutsFluent) {
+ auto entry = m_shuffleboardInstance->GetTab("Tab")
+ .GetLayout("First", "List")
+ .GetLayout("Second", "List")
+ .GetLayout("Third", "List")
+ .GetLayout("Fourth", "List")
+ .Add("Value", "string")
+ .GetEntry();
+
+ EXPECT_EQ("string", entry.GetString("")) << "Wrong entry value";
+ EXPECT_EQ("/Shuffleboard/Tab/First/Second/Third/Fourth/Value",
+ entry.GetName())
+ << "Entry path generated incorrectly";
+}
+
+TEST_F(ShuffleboardInstanceTest, NestedLayoutsOop) {
+ ShuffleboardTab& tab = m_shuffleboardInstance->GetTab("Tab");
+ ShuffleboardLayout& first = tab.GetLayout("First", "List");
+ ShuffleboardLayout& second = first.GetLayout("Second", "List");
+ ShuffleboardLayout& third = second.GetLayout("Third", "List");
+ ShuffleboardLayout& fourth = third.GetLayout("Fourth", "List");
+ SimpleWidget& widget = fourth.Add("Value", "string");
+ auto entry = widget.GetEntry();
+
+ EXPECT_EQ("string", entry.GetString("")) << "Wrong entry value";
+ EXPECT_EQ("/Shuffleboard/Tab/First/Second/Third/Fourth/Value",
+ entry.GetName())
+ << "Entry path generated incorrectly";
+}
+
+TEST_F(ShuffleboardInstanceTest, LayoutTypeIsSet) {
+ std::string layoutType = "Type";
+ m_shuffleboardInstance->GetTab("Tab").GetLayout("Title", layoutType);
+ m_shuffleboardInstance->Update();
+ nt::NetworkTableEntry entry = m_ntInstance.GetEntry(
+ "/Shuffleboard/.metadata/Tab/Title/PreferredComponent");
+ EXPECT_EQ(layoutType, entry.GetString("Not Set")) << "Layout type not set";
+}
+
+TEST_F(ShuffleboardInstanceTest, NestedActuatorWidgetsAreDisabled) {
+ MockActuatorSendable sendable("Actuator");
+ m_shuffleboardInstance->GetTab("Tab")
+ .GetLayout("Title", "Type")
+ .Add(sendable);
+ auto controllableEntry =
+ m_ntInstance.GetEntry("/Shuffleboard/Tab/Title/Actuator/.controllable");
+ m_shuffleboardInstance->Update();
+
+ // Note: we use the unsafe `GetBoolean()` method because if the value is NOT
+ // a boolean, or if it is not present, then something has clearly gone very,
+ // very wrong
+ bool controllable = controllableEntry.GetValue()->GetBoolean();
+ // Sanity check
+ EXPECT_TRUE(controllable)
+ << "The nested actuator widget should be enabled by default";
+ m_shuffleboardInstance->DisableActuatorWidgets();
+ controllable = controllableEntry.GetValue()->GetBoolean();
+ EXPECT_FALSE(controllable)
+ << "The nested actuator widget should have been disabled";
+}
diff --git a/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardTabTest.cpp b/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardTabTest.cpp
new file mode 100644
index 0000000..23f3e3a
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardTabTest.cpp
@@ -0,0 +1,115 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 <array>
+#include <memory>
+#include <string>
+
+#include <networktables/NetworkTableEntry.h>
+#include <networktables/NetworkTableInstance.h>
+
+#include "frc/commands/InstantCommand.h"
+#include "frc/shuffleboard/ShuffleboardInstance.h"
+#include "frc/shuffleboard/ShuffleboardTab.h"
+#include "frc/smartdashboard/Sendable.h"
+#include "gtest/gtest.h"
+
+using namespace frc;
+
+class ShuffleboardTabTest : public testing::Test {
+ void SetUp() override {
+ m_ntInstance = nt::NetworkTableInstance::Create();
+ m_instance = std::make_unique<detail::ShuffleboardInstance>(m_ntInstance);
+ m_tab = &(m_instance->GetTab("Tab"));
+ }
+
+ protected:
+ nt::NetworkTableInstance m_ntInstance;
+ ShuffleboardTab* m_tab;
+ std::unique_ptr<detail::ShuffleboardInstance> m_instance;
+};
+
+TEST_F(ShuffleboardTabTest, AddDouble) {
+ auto entry = m_tab->Add("Double", 1.0).GetEntry();
+ EXPECT_EQ("/Shuffleboard/Tab/Double", entry.GetName());
+ EXPECT_FLOAT_EQ(1.0, entry.GetValue()->GetDouble());
+}
+
+TEST_F(ShuffleboardTabTest, AddInteger) {
+ auto entry = m_tab->Add("Int", 1).GetEntry();
+ EXPECT_EQ("/Shuffleboard/Tab/Int", entry.GetName());
+ EXPECT_FLOAT_EQ(1.0, entry.GetValue()->GetDouble());
+}
+
+TEST_F(ShuffleboardTabTest, AddBoolean) {
+ auto entry = m_tab->Add("Bool", false).GetEntry();
+ EXPECT_EQ("/Shuffleboard/Tab/Bool", entry.GetName());
+ EXPECT_FALSE(entry.GetValue()->GetBoolean());
+}
+
+TEST_F(ShuffleboardTabTest, AddString) {
+ auto entry = m_tab->Add("String", "foobar").GetEntry();
+ EXPECT_EQ("/Shuffleboard/Tab/String", entry.GetName());
+ EXPECT_EQ("foobar", entry.GetValue()->GetString());
+}
+
+TEST_F(ShuffleboardTabTest, AddNamedSendableWithProperties) {
+ InstantCommand sendable("Command");
+ std::string widgetType = "Command Widget";
+ wpi::StringMap<std::shared_ptr<nt::Value>> map;
+ map.try_emplace("foo", nt::Value::MakeDouble(1234));
+ map.try_emplace("bar", nt::Value::MakeString("baz"));
+ m_tab->Add(sendable).WithWidget(widgetType).WithProperties(map);
+
+ m_instance->Update();
+ std::string meta = "/Shuffleboard/.metadata/Tab/Command";
+
+ EXPECT_EQ(1234, m_ntInstance.GetEntry(meta + "/Properties/foo").GetDouble(-1))
+ << "Property 'foo' not set correctly";
+ EXPECT_EQ("baz",
+ m_ntInstance.GetEntry(meta + "/Properties/bar").GetString(""))
+ << "Property 'bar' not set correctly";
+ EXPECT_EQ(widgetType,
+ m_ntInstance.GetEntry(meta + "/PreferredComponent").GetString(""))
+ << "Preferred component not set correctly";
+}
+
+TEST_F(ShuffleboardTabTest, AddNumberArray) {
+ std::array<double, 3> expect = {{1.0, 2.0, 3.0}};
+ auto entry = m_tab->Add("DoubleArray", expect).GetEntry();
+ EXPECT_EQ("/Shuffleboard/Tab/DoubleArray", entry.GetName());
+
+ auto actual = entry.GetValue()->GetDoubleArray();
+ EXPECT_EQ(expect.size(), actual.size());
+ for (size_t i = 0; i < expect.size(); i++) {
+ EXPECT_FLOAT_EQ(expect[i], actual[i]);
+ }
+}
+
+TEST_F(ShuffleboardTabTest, AddBooleanArray) {
+ std::array<bool, 2> expect = {{true, false}};
+ auto entry = m_tab->Add("BoolArray", expect).GetEntry();
+ EXPECT_EQ("/Shuffleboard/Tab/BoolArray", entry.GetName());
+
+ auto actual = entry.GetValue()->GetBooleanArray();
+ EXPECT_EQ(expect.size(), actual.size());
+ for (size_t i = 0; i < expect.size(); i++) {
+ EXPECT_EQ(expect[i], actual[i]);
+ }
+}
+
+TEST_F(ShuffleboardTabTest, AddStringArray) {
+ std::array<std::string, 2> expect = {{"foo", "bar"}};
+ auto entry = m_tab->Add("StringArray", expect).GetEntry();
+ EXPECT_EQ("/Shuffleboard/Tab/StringArray", entry.GetName());
+
+ auto actual = entry.GetValue()->GetStringArray();
+ EXPECT_EQ(expect.size(), actual.size());
+ for (size_t i = 0; i < expect.size(); i++) {
+ EXPECT_EQ(expect[i], actual[i]);
+ }
+}
diff --git a/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardTest.cpp b/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardTest.cpp
new file mode 100644
index 0000000..d39d59d
--- /dev/null
+++ b/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardTest.cpp
@@ -0,0 +1,20 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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 "frc/shuffleboard/Shuffleboard.h"
+#include "frc/shuffleboard/ShuffleboardTab.h"
+#include "gtest/gtest.h"
+
+using namespace frc;
+
+class ShuffleboardTest : public testing::Test {};
+
+TEST_F(ShuffleboardTest, TabObjectsCached) {
+ ShuffleboardTab& tab1 = Shuffleboard::GetTab("testTabObjectsCached");
+ ShuffleboardTab& tab2 = Shuffleboard::GetTab("testTabObjectsCached");
+ EXPECT_EQ(&tab1, &tab2) << "Tab objects were not cached";
+}
diff --git a/wpilibc/src/test/native/include/MockSpeedController.h b/wpilibc/src/test/native/include/MockSpeedController.h
new file mode 100644
index 0000000..e0c788f
--- /dev/null
+++ b/wpilibc/src/test/native/include/MockSpeedController.h
@@ -0,0 +1,30 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "frc/SpeedController.h"
+
+namespace frc {
+
+class MockSpeedController : public SpeedController {
+ public:
+ void Set(double speed) override;
+ double Get() const override;
+ void SetInverted(bool isInverted) override;
+ bool GetInverted() const override;
+ void Disable() override;
+ void StopMotor() override;
+
+ void PIDWrite(double output) override;
+
+ private:
+ double m_speed = 0.0;
+ bool m_isInverted = false;
+};
+
+} // namespace frc
diff --git a/wpilibc/src/test/native/include/shuffleboard/MockActuatorSendable.h b/wpilibc/src/test/native/include/shuffleboard/MockActuatorSendable.h
new file mode 100644
index 0000000..f56215c
--- /dev/null
+++ b/wpilibc/src/test/native/include/shuffleboard/MockActuatorSendable.h
@@ -0,0 +1,27 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2018 FIRST. 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. */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <wpi/StringRef.h>
+
+#include "frc/smartdashboard/SendableBase.h"
+#include "frc/smartdashboard/SendableBuilder.h"
+
+namespace frc {
+
+/**
+ * A mock sendable that marks itself as an actuator.
+ */
+class MockActuatorSendable : public SendableBase {
+ public:
+ explicit MockActuatorSendable(wpi::StringRef name);
+
+ void InitSendable(SendableBuilder& builder) override;
+};
+
+} // namespace frc