Squashed 'third_party/allwpilib_2019/' changes from 936627bd9..a3f7420da

e20d96ea4 Use __has_include for WPILib.h (#2164)
a76d006a0 Update native-utils to 2020.7.2 (#2161)
24c031d69 Increase SPI auto byte count to allow 32 bytes to be sent (#2163)
6b4eecf5f Add hidden functions to get the SPI system and SPI DMA (#2162)
ccdd0fbdb Add TrapezoidProfile external PID examples (#2131)
5c6b8a0f4 Replace std::is_pod_v with std::is_standard_layout_v (#2159)
67d2fed68 Add DutyCycleEncoder channel constructor (#2158)
d8f11eb14 Hardcode channels for LSB weight (#2153)
b2ae75acd Add way to disable "no extensions found" message (#2134)
4f951789f Build testbench tests online inorder to improve speed (#2144)
005c4c5be Try catch around task dependencies to fix loading in editor (#2156)
34f6b3f4c Fix C++ RamseteCommand param doxygen (#2157)
f7a93713f Fix up templated TrapezoidProfile classes (#2151)
8c2ff94d7 Rename MathUtils to MathUtil for consistency with other util classes (#2155)
d003ec2dc Update to 2020v9 image (#2154)
8e7cc3fe7 Add user-friendly SimDeviceSim wrappers (#2150)
6c8f6cf47 Fix bug in cubic and quintic hermetic spline generation (#2139)
e37ecd33a Sim GUI: Add support for LED displays (#2138)
57c5523d6 Fix documentation in RamseteCommand (#2149)
7b9c6ebc2 Fix wpiutilJNIShared linkage typo in wpilibj (#2143)
9a515c80f Template C++ LinearFilter to work with unit types (#2142)
5b73c17f2 Remove encoder velocities methods in DifferentialDriveOdometry (#2147)
b8c102426 Fix PS3Eye VID and PID (#2146)
2622c6c29 Add default values for b and zeta in RamseteController (#2145)
f66ae5999 Add HSV helpers to AddressableLED (#2135)
5e97c81d8 Add MedianFilter class for moving-window median (#2136)
f79b7a058 Remove unnecessary constructor arg for LinearFilter's circular buffers (#2140)
e49494830 Replace Jenkins with Azure agent (#1914)
b67d049ac Check status of PDP CAN reads (#2126)
70102a60b SendableRegistry.foreachLiveWindow: Prevent concurrent modification (#2129)
6dcd2b0e2 Improve various subsystem APIs (#2130)
ce3973435 HAL_CAN_ReceiveMessage: return MessageNotFound if no callbacks registered (#2133)
3fcfc8ea7 Fix double disable segfaulting interrupts (#2132)
6ceafe3cd Fix class reference for logger (#2123)
b058dcf64 Catch exceptions generated by OpenCV in cscore JNI (#2118)
0b9307fdf Remove unused parts of .styleguide files (#2119)
39be812b2 Fix C++ ArmFeedforward (#2120)
21e957ee4 Add DifferentialDrive voltage constraint (#2075)
e0bc97f66 Add ProfiledPIDSubsystem example (#2076)
3df44c874 Remove Rotation2d.h wpi/math include (#2117)
a58dbec8a Add holonomic follower examples (#2052)
9a8067465 Fix incomplete .styleguide (#2113)
ffa4b907c Fix C++ floating point literal formatting (#2114)
3d1ca856b Fix missing typename and return type (#2115)
5f85457a9 Add usage reporting for AddressableLED (#2108)
4ebae1712 Enforce leading/trailing zeros in Java numeric constants (#2105)
fa85fbfc1 Template C++ TrapezoidProfile and ProfiledPIDController on units (#2109)
f62e23f1a Add Doxygen for new HAL interfaces (#2110)
5443fdabc Directly construct PWM port from HAL, avoid wpilib PWM object (#2106)
c0e36df9d Standardize on PWMVictorSPX in examples (#2104)
8c4d9f541 Add TrapezoidProfileSubsystem (#2077)
45201d15f Add encoder distance overload to DifferentialDriveOdometry (#2096)
845aba33f Make feedforward classes constexpr (#2103)
500c43fb8 Add examples for DMA, DutyCycle, DutyCycleEncoder and AddressableLED (#2100)
589162811 Use DifferentialDriveWheelSpeeds in RamseteCommand ctor (#2091)
b37b68daa Add JRE deployment to MyRobot Deploy (#2099)
0e83c65d2 Fix small logic error in ParallelDeadlineGroup (#2095)
6f6c6da9f Updates to addressable LED (#2098)
1894219ef Fix devmain package in commands (#2097)
77a9949bb Add AddressableLED simulation GUI support
a4c9e4ec2 Add AddressableLED simulation support
8ed205907 Add AddressableLED (#2092)
59507b12d Bump to 2020 v7 image (#2086)
5d39bf806 Make halsimgui::DrawLEDs() values parameter const (#2088)
841ef91c0 Use gyro angle instead of robot angle for odometry (#2081)
1b66ead49 Use standard constant for pi instead of 3.14 (#2084)
db2c3dddd Use DMA Global Number for DMA Index (#2085)
82b2170fe Add DMA support to HAL and WPILibC (#2080)
8280b7e3a Add DutyCycleEncoder and AnalogEncoder (#2040)
551096006 Use kNumSystems for DutyCycle count in Ports (#2083)
df1065218 Remove release configs of deploy in MyRobot (#2082)
bf5388393 Add deploy options to myRobot (#2079)
b7bc1ea74 Update to 2020v6 image (#2078)
708009cd2 Update to gradle 6.0 (#2074)
3cce61b89 Add SmartDashboard::GetEntry function in C++ (#2064)
565e1f3e7 Fix spelling in MecanumDriveOdometry docs (#2072)
1853f7b6b Add timing window to simulation GUI
c5a049712 Add simulation pause/resume/step support
f5446c740 Add Notifier HALSIM access
3e049e02f Add name to HAL Notifier
2da64d15f Make usage reporting enums type match (#2069)
f04d95e50 Make FRCUsageReporting.h C-compatible (#2070)
d748c67a5 Generate docs for command libraries and fix doclint enable (#2071)
55a7f2b4a Add template for old command-based style (#2031)
486fa9c69 Add XboxController examples for arcade and tank drive (#2058)
e3dd1c5d7 Fix small bug in SplineHelper (#2061)
7dc7c71b5 Add feedforward components (#2045)
5f33d6af1 Fix ProfiledPIDSubsystem parameter name (#2017)
94843adb8 Standardize documentation of Speed Controllers bounds (#2043)
9bcff37b9 Add HAL specific version of wpi_setError (#2055)
326aecc9a Add error message for CAN Write Overrun (#2062)
00228678d Add requirements param to more Command APIs (#2059)
ff39a96ce Make DigitalOutput a DigitalSource (#2054)
5ccad2e8a Fix frc2::Timer returning incorrect timestamp values (#2057)
629e95776 Add VendorDeps JSON files for command libraries (#2048)
6858a57f7 Make notifier command tests a lot more lenient (#2056)
0ebe32823 Fix MyRobotStatic accidentally linking to shared command libs (#2046)
384d00f9e Fix various duty cycle bugs (#2047)
1f6850adf Add CAN Manufacturer for Studica (#2050)
7508aada9 Add ability to end startCompetition() main loop (#2032)
f5b4be16d Old C++ Command: Make GetName et al public (#2042)
e6f5c93ab Clean up new C++ commands (#2027)
39f46ceab Don't allow rising and falling values to be read from AnalogTrigger (#2039)
d93aa2b6b Add missing lock in FRCDriverStation (#2034)
114ddaf81 Fix duplicate encoders in examples (#2033)
f22d0961e Sim GUI: Add duty cycle support
3262c2bad Sim GUI: Use new multi-channel PDP getter function
96d40192a Revert accidental change to MyRobot.cpp (#2029)
ed30d5d40 Add JSON support for Trajectories (#2025)
2b6811edd Fix null pointer dereference in C++ CommandScheduler (#2023)
1d695a166 Add FPGA Duty Cycle support (#1987)
509819d83 Split the two command implementations into separate libraries (#2012)
2ad15cae1 Add multi PDP getter and sim PCM/PDP multi arg functions (#2014)
931b8ceef Add new usage reporting types from 2020v5 (#2026)
0b3821eba Change files with CRLF line endings to LF (#2022)
6f159d142 Add way to atomically check for new data, and wait otherwise (#2015)
a769f1f22 Fix bug in RamseteCommand (using degrees instead of radians) (#2020)
c5186d815 Clean up PIDCommand (#2010)
9ebd23d61 Add setVoltage method to SpeedController (#1997)
f6e311ef8 Fix SplineHelper bug (#2018)
f33bd9f05 Fix NPE in RamseteCommand (#2019)
1c1e0c9a6 Add HAL_SetAllSolenoids to sim (#2004)
ea9bb651a Remove accidental OpenCV link from wpilibc shared library (#2013)
cc0742518 Change command decorators to return implementation (#2007)
16b34cce2 Remove IterativeRobot templates (#2011)
669127e49 Update intellisense to work with Beta 2020 code (#2008)
9dc30797e Fix usage reporting indices (#2009)
f6b844ea3 Move HAL Interrupt struct to anonymous namespace (#2003)
a72f80991 Add extern C to DigitalGlitchFilterJNI (#2002)
916596cb0 Fix invalid examples json, add validator (#2001)
5509a8e96 Use constexpr for all example constants
0be6b6475 Use constexpr for DifferentialDriveKinematics

Change-Id: I1416646cbab487ad8021830215766d8ec7f24ddc
git-subtree-dir: third_party/allwpilib_2019
git-subtree-split: a3f7420dab7a104c27a0c3bf0872c999c98fd9a9
diff --git a/simulation/gz_msgs/build.gradle b/simulation/gz_msgs/build.gradle
index 44f9692..353f4ad 100644
--- a/simulation/gz_msgs/build.gradle
+++ b/simulation/gz_msgs/build.gradle
@@ -1,95 +1,95 @@
-plugins {

-    id 'cpp'

-    id 'java'

-    id 'com.google.protobuf' version '0.8.8'

-    id 'edu.wpi.first.NativeUtils'

-}

-

-description = "A C++ and Java library to pass FRC Simulation Messages in and out of Gazebo."

-

-/* The simulation does not run on real hardware; so we always skip Athena */

-ext.skiplinuxathena = true

-ext.skiplinuxraspbian = true

-apply from: "${rootDir}/shared/config.gradle"

-

-/* Use a sort of poor man's autoconf to find the protobuf development

-   files; on Debian, those are supplied by libprotobuf-dev.

-

-   This should get skipped on Windows.

-

-   TODO:  Add Windows support for the simulation code */

-

-def protobuf_version = ""

-try {

-    protobuf_version = "pkg-config --modversion protobuf".execute().text.trim()

-    println "Protobuf version is [${protobuf_version}]"

-} catch(Exception ex) {

-}

-

-if (!protobuf_version?.trim()) {

-    println "Protobuf is not available. (pkg-config --modversion protobuf failed)"

-    protobuf_version = "+"

-    if (project.hasProperty("makeSim")) {

-        /* Force the build even though we did not find protobuf. */

-        println "makeSim set. Forcing build - failure likely."

-    }

-    else {

-        ext.skip_gz_msgs = true

-        println "Skipping gz_msgs."

-    }

-}

-

-tasks.whenTaskAdded { task ->

-    task.onlyIf { !project.hasProperty('skip_gz_msgs') }

-}

-

-dependencies {

-      compile "com.google.protobuf:protobuf-java:${protobuf_version}"

-      compile "com.google.protobuf:protoc:${protobuf_version}"

-}

-

-/* There is a nice gradle plugin for protobuf, and the protoc tool

-   is included; using it simplifies our build process.

-   The trick is that we have to use the same version as the system

-   copy of libprotobuf-dev */

-protobuf {

-    protoc {

-        artifact = "com.google.protobuf:protoc:${protobuf_version}"

-    }

-

-    generatedFilesBaseDir = "$buildDir/generated"

-    generateProtoTasks {

-        all().each { task ->

-            task.builtins {

-                cpp {

-                    outputSubDir = 'simulation/gz_msgs'

-                }

-            }

-        }

-    }

-}

-

-model {

-    components {

-        gz_msgs(NativeLibrarySpec) {

-            sources {

-                cpp {

-                    source {

-                        srcDir "$buildDir/generated/main/simulation/gz_msgs"

-                        builtBy tasks.generateProto

-                    }

-                    exportedHeaders {

-                        srcDir "src/include"

-                        srcDir "$buildDir/generated/main"

-                    }

-                }

-            }

-            /* We must compile with -fPIC to link the static library into an so */

-            binaries {

-                all {

-                    cppCompiler.args "-fPIC"

-                }

-            }

-        }

-    }

-}

+plugins {
+    id 'cpp'
+    id 'java'
+    id 'com.google.protobuf' version '0.8.8'
+    id 'edu.wpi.first.NativeUtils'
+}
+
+description = "A C++ and Java library to pass FRC Simulation Messages in and out of Gazebo."
+
+/* The simulation does not run on real hardware; so we always skip Athena */
+ext.skiplinuxathena = true
+ext.skiplinuxraspbian = true
+apply from: "${rootDir}/shared/config.gradle"
+
+/* Use a sort of poor man's autoconf to find the protobuf development
+   files; on Debian, those are supplied by libprotobuf-dev.
+
+   This should get skipped on Windows.
+
+   TODO:  Add Windows support for the simulation code */
+
+def protobuf_version = ""
+try {
+    protobuf_version = "pkg-config --modversion protobuf".execute().text.trim()
+    println "Protobuf version is [${protobuf_version}]"
+} catch(Exception ex) {
+}
+
+if (!protobuf_version?.trim()) {
+    println "Protobuf is not available. (pkg-config --modversion protobuf failed)"
+    protobuf_version = "+"
+    if (project.hasProperty("makeSim")) {
+        /* Force the build even though we did not find protobuf. */
+        println "makeSim set. Forcing build - failure likely."
+    }
+    else {
+        ext.skip_gz_msgs = true
+        println "Skipping gz_msgs."
+    }
+}
+
+tasks.whenTaskAdded { task ->
+    task.onlyIf { !project.hasProperty('skip_gz_msgs') }
+}
+
+dependencies {
+      implementation "com.google.protobuf:protobuf-java:${protobuf_version}"
+      implementation "com.google.protobuf:protoc:${protobuf_version}"
+}
+
+/* There is a nice gradle plugin for protobuf, and the protoc tool
+   is included; using it simplifies our build process.
+   The trick is that we have to use the same version as the system
+   copy of libprotobuf-dev */
+protobuf {
+    protoc {
+        artifact = "com.google.protobuf:protoc:${protobuf_version}"
+    }
+
+    generatedFilesBaseDir = "$buildDir/generated"
+    generateProtoTasks {
+        all().each { task ->
+            task.builtins {
+                cpp {
+                    outputSubDir = 'simulation/gz_msgs'
+                }
+            }
+        }
+    }
+}
+
+model {
+    components {
+        gz_msgs(NativeLibrarySpec) {
+            sources {
+                cpp {
+                    source {
+                        srcDir "$buildDir/generated/main/simulation/gz_msgs"
+                        builtBy tasks.generateProto
+                    }
+                    exportedHeaders {
+                        srcDir "src/include"
+                        srcDir "$buildDir/generated/main"
+                    }
+                }
+            }
+            /* We must compile with -fPIC to link the static library into an so */
+            binaries {
+                all {
+                    cppCompiler.args "-fPIC"
+                }
+            }
+        }
+    }
+}
diff --git a/simulation/halsim_ds_socket/build.gradle b/simulation/halsim_ds_socket/build.gradle
index 46e48f4..440e5d9 100644
--- a/simulation/halsim_ds_socket/build.gradle
+++ b/simulation/halsim_ds_socket/build.gradle
@@ -48,6 +48,9 @@
             project(':hal').addHalDependency(it, 'shared')
             lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
             lib library: pluginName, linkage: 'shared'
+            if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
+                nativeUtils.useRequiredLibrary(it, 'netcomm_shared', 'chipobject_shared', 'visa_shared', 'ni_runtime_shared')
+            }
         }
     }
 }
diff --git a/simulation/halsim_ds_socket/src/dev/native/cpp/main.cpp b/simulation/halsim_ds_socket/src/dev/native/cpp/main.cpp
index aba88fb..2c1e83a 100644
--- a/simulation/halsim_ds_socket/src/dev/native/cpp/main.cpp
+++ b/simulation/halsim_ds_socket/src/dev/native/cpp/main.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018 FIRST. All Rights Reserved.                             */
+/* Copyright (c) 2018-2019 FIRST. All Rights Reserved.                        */
 /* Open Source Software - may be modified and shared by FRC teams. The code   */
 /* must be accompanied by the FIRST BSD license file in the root directory of */
 /* the project.                                                               */
@@ -7,7 +7,8 @@
 
 #include <thread>
 
-#include <hal/HAL.h>
+#include <hal/DriverStation.h>
+#include <hal/HALBase.h>
 #include <wpi/Format.h>
 #include <wpi/raw_ostream.h>
 
diff --git a/simulation/halsim_ds_socket/src/test/native/cpp/main.cpp b/simulation/halsim_ds_socket/src/test/native/cpp/main.cpp
index fd8f022..c6b6c58 100644
--- a/simulation/halsim_ds_socket/src/test/native/cpp/main.cpp
+++ b/simulation/halsim_ds_socket/src/test/native/cpp/main.cpp
@@ -5,7 +5,7 @@
 /* the project.                                                               */
 /*----------------------------------------------------------------------------*/
 
-#include <hal/HAL.h>
+#include <hal/HALBase.h>
 
 #include "gtest/gtest.h"
 
diff --git a/simulation/halsim_gui/build.gradle b/simulation/halsim_gui/build.gradle
index 5ac68ea..5df5302 100644
--- a/simulation/halsim_gui/build.gradle
+++ b/simulation/halsim_gui/build.gradle
@@ -1,40 +1,40 @@
-if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) {

-

-    description = "A plugin that creates a simulation gui"

-

-    ext {

-        includeWpiutil = true

-        pluginName = 'halsim_gui'

-    }

-

-    apply plugin: 'google-test-test-suite'

-

-

-    ext {

-        staticGtestConfigs = [:]

-    }

-

-    staticGtestConfigs["${pluginName}Test"] = []

-    apply from: "${rootDir}/shared/googletest.gradle"

-

-    apply from: "${rootDir}/shared/plugins/setupBuild.gradle"

-

-    model {

-        binaries {

-            all {

-                nativeUtils.useRequiredLibrary(it, 'imgui_static')

-                if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) {

-                    it.buildable = false

-                    return

-                }

-                if (it.targetPlatform.operatingSystem.isWindows()) {

-                    it.linker.args << 'Gdi32.lib' << 'Shell32.lib'

-                } else if (it.targetPlatform.operatingSystem.isMacOsX()) {

-                    it.linker.args << '-framework' << 'Cocoa' << '-framework' << 'IOKit' << '-framework' << 'CoreFoundation' << '-framework' << 'CoreVideo'

-                } else {

-                    it.linker.args << '-lX11' << '-lvulkan'

-                }

-            }

-        }

-    }

-}

+if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) {
+
+    description = "A plugin that creates a simulation gui"
+
+    ext {
+        includeWpiutil = true
+        pluginName = 'halsim_gui'
+    }
+
+    apply plugin: 'google-test-test-suite'
+
+
+    ext {
+        staticGtestConfigs = [:]
+    }
+
+    staticGtestConfigs["${pluginName}Test"] = []
+    apply from: "${rootDir}/shared/googletest.gradle"
+
+    apply from: "${rootDir}/shared/plugins/setupBuild.gradle"
+
+    model {
+        binaries {
+            all {
+                nativeUtils.useRequiredLibrary(it, 'imgui_static')
+                if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) {
+                    it.buildable = false
+                    return
+                }
+                if (it.targetPlatform.operatingSystem.isWindows()) {
+                    it.linker.args << 'Gdi32.lib' << 'Shell32.lib'
+                } else if (it.targetPlatform.operatingSystem.isMacOsX()) {
+                    it.linker.args << '-framework' << 'Cocoa' << '-framework' << 'IOKit' << '-framework' << 'CoreFoundation' << '-framework' << 'CoreVideo'
+                } else {
+                    it.linker.args << '-lX11' << '-lvulkan'
+                }
+            }
+        }
+    }
+}
diff --git a/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.cpp b/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.cpp
new file mode 100644
index 0000000..606eac5
--- /dev/null
+++ b/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.cpp
@@ -0,0 +1,160 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2019 FIRST. All Rights Reserved.                             */
+/* Open Source Software - may be 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 "AddressableLEDGui.h"
+
+#include <cstdio>
+#include <cstring>
+#include <vector>
+
+#include <hal/Ports.h>
+#include <imgui.h>
+#include <imgui_internal.h>
+#include <mockdata/AddressableLEDData.h>
+#include <wpi/SmallVector.h>
+#include <wpi/StringRef.h>
+
+#include "ExtraGuiWidgets.h"
+#include "HALSimGui.h"
+
+using namespace halsimgui;
+
+namespace {
+struct LEDDisplaySettings {
+  int numColumns = 10;
+  LEDConfig config;
+};
+}  // namespace
+
+static std::vector<LEDDisplaySettings> displaySettings;
+
+// read/write columns setting to ini file
+static void* AddressableLEDReadOpen(ImGuiContext* ctx,
+                                    ImGuiSettingsHandler* handler,
+                                    const char* name) {
+  int num;
+  if (wpi::StringRef{name}.getAsInteger(10, num)) return nullptr;
+  if (num < 0) return nullptr;
+  if (num >= static_cast<int>(displaySettings.size()))
+    displaySettings.resize(num + 1);
+  return &displaySettings[num];
+}
+
+static void AddressableLEDReadLine(ImGuiContext* ctx,
+                                   ImGuiSettingsHandler* handler, void* entry,
+                                   const char* lineStr) {
+  auto* settings = static_cast<LEDDisplaySettings*>(entry);
+  // format: columns=#
+  wpi::StringRef line{lineStr};
+  auto [name, value] = line.split('=');
+  name = name.trim();
+  value = value.trim();
+  if (name == "columns") {
+    int num;
+    if (value.getAsInteger(10, num)) return;
+    settings->numColumns = num;
+  } else if (name == "serpentine") {
+    int num;
+    if (value.getAsInteger(10, num)) return;
+    settings->config.serpentine = num != 0;
+  } else if (name == "order") {
+    int num;
+    if (value.getAsInteger(10, num)) return;
+    settings->config.order = static_cast<LEDConfig::Order>(num);
+  } else if (name == "start") {
+    int num;
+    if (value.getAsInteger(10, num)) return;
+    settings->config.start = static_cast<LEDConfig::Start>(num);
+  }
+}
+
+static void AddressableLEDWriteAll(ImGuiContext* ctx,
+                                   ImGuiSettingsHandler* handler,
+                                   ImGuiTextBuffer* out_buf) {
+  for (size_t i = 0; i < displaySettings.size(); ++i) {
+    out_buf->appendf(
+        "[AddressableLED][%d]\ncolumns=%d\nserpentine=%d\norder=%d\n"
+        "start=%d\n\n",
+        static_cast<int>(i), displaySettings[i].numColumns,
+        displaySettings[i].config.serpentine ? 1 : 0,
+        static_cast<int>(displaySettings[i].config.order),
+        static_cast<int>(displaySettings[i].config.start));
+  }
+}
+
+static void DisplayAddressableLEDs() {
+  bool hasAny = false;
+  static const int numLED = HAL_GetNumAddressableLEDs();
+  if (numLED > static_cast<int>(displaySettings.size()))
+    displaySettings.resize(numLED);
+
+  for (int i = 0; i < numLED; ++i) {
+    if (!HALSIM_GetAddressableLEDInitialized(i)) continue;
+    hasAny = true;
+
+    if (numLED > 1) ImGui::Text("LEDs[%d]", i);
+
+    static HAL_AddressableLEDData data[HAL_kAddressableLEDMaxLength];
+    int length = HALSIM_GetAddressableLEDData(i, data);
+    bool running = HALSIM_GetAddressableLEDRunning(i);
+
+    ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
+    ImGui::LabelText("Length", "%d", length);
+    ImGui::LabelText("Running", "%s", running ? "Yes" : "No");
+    ImGui::InputInt("Columns", &displaySettings[i].numColumns);
+    {
+      static const char* options[] = {"Row Major", "Column Major"};
+      int val = displaySettings[i].config.order;
+      if (ImGui::Combo("Order", &val, options, 2))
+        displaySettings[i].config.order = static_cast<LEDConfig::Order>(val);
+    }
+    {
+      static const char* options[] = {"Upper Left", "Lower Left", "Upper Right",
+                                      "Lower Right"};
+      int val = displaySettings[i].config.start;
+      if (ImGui::Combo("Start", &val, options, 4))
+        displaySettings[i].config.start = static_cast<LEDConfig::Start>(val);
+    }
+    ImGui::Checkbox("Serpentine", &displaySettings[i].config.serpentine);
+    if (displaySettings[i].numColumns < 1) displaySettings[i].numColumns = 1;
+    ImGui::PopItemWidth();
+
+    // show as LED indicators
+    static int values[HAL_kAddressableLEDMaxLength];
+    static ImU32 colors[HAL_kAddressableLEDMaxLength];
+
+    if (!running) {
+      colors[0] = IM_COL32(128, 128, 128, 255);
+      for (int j = 0; j < length; ++j) values[j] = -1;
+    } else {
+      for (int j = 0; j < length; ++j) {
+        values[j] = j + 1;
+        colors[j] = IM_COL32(data[j].r, data[j].g, data[j].b, 255);
+      }
+    }
+
+    DrawLEDs(values, length, displaySettings[i].numColumns, colors, 0, 0,
+             displaySettings[i].config);
+  }
+  if (!hasAny) ImGui::Text("No addressable LEDs");
+}
+
+void AddressableLEDGui::Initialize() {
+  // hook ini handler to save columns settings
+  ImGuiSettingsHandler iniHandler;
+  iniHandler.TypeName = "AddressableLED";
+  iniHandler.TypeHash = ImHashStr(iniHandler.TypeName);
+  iniHandler.ReadOpenFn = AddressableLEDReadOpen;
+  iniHandler.ReadLineFn = AddressableLEDReadLine;
+  iniHandler.WriteAllFn = AddressableLEDWriteAll;
+  ImGui::GetCurrentContext()->SettingsHandlers.push_back(iniHandler);
+
+  HALSimGui::AddWindow("Addressable LEDs", DisplayAddressableLEDs,
+                       ImGuiWindowFlags_AlwaysAutoResize);
+  HALSimGui::SetWindowVisibility("Addressable LEDs", HALSimGui::kHide);
+  HALSimGui::SetDefaultWindowPos("Addressable LEDs", 290, 100);
+}
diff --git a/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.h b/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.h
new file mode 100644
index 0000000..e376b9b
--- /dev/null
+++ b/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.h
@@ -0,0 +1,17 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2019 FIRST. All Rights Reserved.                             */
+/* Open Source Software - may be modified and 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 halsimgui {
+
+class AddressableLEDGui {
+ public:
+  static void Initialize();
+};
+
+}  // namespace halsimgui
diff --git a/simulation/halsim_gui/src/main/native/cpp/DIOGui.cpp b/simulation/halsim_gui/src/main/native/cpp/DIOGui.cpp
index 93a07f9..7c9eae5 100644
--- a/simulation/halsim_gui/src/main/native/cpp/DIOGui.cpp
+++ b/simulation/halsim_gui/src/main/native/cpp/DIOGui.cpp
@@ -15,6 +15,7 @@
 #include <imgui.h>
 #include <mockdata/DIOData.h>
 #include <mockdata/DigitalPWMData.h>
+#include <mockdata/DutyCycleData.h>
 #include <mockdata/EncoderData.h>
 #include <mockdata/SimDeviceData.h>
 
@@ -33,11 +34,14 @@
   static int numDIO = HAL_GetNumDigitalChannels();
   static int numPWM = HAL_GetNumDigitalPWMOutputs();
   static int numEncoder = HAL_GetNumEncoders();
+  static int numDutyCycle = HAL_GetNumDutyCycles();
   static auto pwmMap = std::make_unique<int[]>(numDIO);
   static auto encoderMap = std::make_unique<int[]>(numDIO);
+  static auto dutyCycleMap = std::make_unique<int[]>(numDIO);
 
   std::memset(pwmMap.get(), 0, numDIO * sizeof(pwmMap[0]));
   std::memset(encoderMap.get(), 0, numDIO * sizeof(encoderMap[0]));
+  std::memset(dutyCycleMap.get(), 0, numDIO * sizeof(dutyCycleMap[0]));
 
   for (int i = 0; i < numPWM; ++i) {
     if (HALSIM_GetDigitalPWMInitialized(i)) {
@@ -56,6 +60,13 @@
     }
   }
 
+  for (int i = 0; i < numDutyCycle; ++i) {
+    if (HALSIM_GetDutyCycleInitialized(i)) {
+      int channel = HALSIM_GetDutyCycleDigitalChannel(i);
+      if (channel >= 0 && channel < numDIO) dutyCycleMap[channel] = i + 1;
+    }
+  }
+
   ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
   for (int i = 0; i < numDIO; ++i) {
     if (HALSIM_GetDIOInitialized(i)) {
@@ -80,6 +91,16 @@
                            HALSIM_GetEncoderDigitalChannelB(encoderMap[i] - 1));
           ImGui::PopStyleColor();
         }
+      } else if (dutyCycleMap[i] > 0) {
+        std::snprintf(name, sizeof(name), "PWM[%d]", i);
+        if (auto simDevice =
+                HALSIM_GetDutyCycleSimDevice(dutyCycleMap[i] - 1)) {
+          LabelSimDevice(name, simDevice);
+        } else {
+          double val = HALSIM_GetDutyCycleOutput(dutyCycleMap[i] - 1);
+          if (ImGui::InputDouble(name, &val))
+            HALSIM_SetDutyCycleOutput(dutyCycleMap[i] - 1, val);
+        }
       } else if (!HALSIM_GetDIOIsInput(i)) {
         std::snprintf(name, sizeof(name), "Out[%d]", i);
         if (auto simDevice = HALSIM_GetDIOSimDevice(i)) {
diff --git a/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp b/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp
index 3cca903..1e2f879 100644
--- a/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp
+++ b/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp
@@ -14,6 +14,7 @@
 #include <imgui.h>
 #include <imgui_internal.h>
 #include <mockdata/DriverStationData.h>
+#include <mockdata/MockHooks.h>
 #include <wpi/Format.h>
 #include <wpi/SmallString.h>
 #include <wpi/StringRef.h>
@@ -328,7 +329,7 @@
 
   // Send new data every 20 ms (may be slower depending on GUI refresh rate)
   static double lastNewDataTime = 0.0;
-  if ((curTime - lastNewDataTime) > 0.02) {
+  if ((curTime - lastNewDataTime) > 0.02 && !HALSIM_IsTimingPaused()) {
     lastNewDataTime = curTime;
     HALSIM_NotifyDriverStationNewData();
   }
@@ -367,7 +368,7 @@
                          ImGuiInputTextFlags_EnterReturnsTrue)) {
     HALSIM_SetDriverStationMatchTime(matchTime);
     startMatchTime = curTime - matchTime;
-  } else if (!HALSIM_GetDriverStationEnabled()) {
+  } else if (!HALSIM_GetDriverStationEnabled() || HALSIM_IsTimingPaused()) {
     startMatchTime = curTime - matchTime;
   } else if (matchTimeEnabled) {
     HALSIM_SetDriverStationMatchTime(curTime - startMatchTime);
diff --git a/simulation/halsim_gui/src/main/native/cpp/ExtraGuiWidgets.cpp b/simulation/halsim_gui/src/main/native/cpp/ExtraGuiWidgets.cpp
index 81a6855..3b1ba28 100644
--- a/simulation/halsim_gui/src/main/native/cpp/ExtraGuiWidgets.cpp
+++ b/simulation/halsim_gui/src/main/native/cpp/ExtraGuiWidgets.cpp
@@ -9,31 +9,88 @@
 
 namespace halsimgui {
 
-void DrawLEDs(int* values, int numValues, int cols, const ImU32* colors,
-              float size, float spacing) {
-  if (numValues == 0) return;
+void DrawLEDs(const int* values, int numValues, int cols, const ImU32* colors,
+              float size, float spacing, const LEDConfig& config) {
+  if (numValues == 0 || cols < 1) return;
   if (size == 0) size = ImGui::GetFontSize() / 2.0;
   if (spacing == 0) spacing = ImGui::GetFontSize() / 3.0;
 
+  int rows = (numValues + cols - 1) / cols;
+  float inc = size + spacing;
+
   ImDrawList* drawList = ImGui::GetWindowDrawList();
   const ImVec2 p = ImGui::GetCursorScreenPos();
-  float x = p.x + size / 2, y = p.y + size / 2;
-  int rows = 1;
-  for (int i = 0; i < numValues; ++i) {
-    if (i >= (rows * cols)) {
-      ++rows;
-      x = p.x + size / 2;
-      y += size + spacing;
-    }
-    if (values[i] > 0)
-      drawList->AddRectFilled(ImVec2(x, y), ImVec2(x + size, y + size),
-                              colors[values[i] - 1]);
-    else if (values[i] < 0)
-      drawList->AddRect(ImVec2(x, y), ImVec2(x + size, y + size),
-                        colors[-values[i] - 1], 0.0f, 0, 1.0);
-    x += size + spacing;
+
+  float ystart, yinc;
+  if (config.start & 1) {
+    // lower
+    ystart = p.y + size / 2 + inc * (rows - 1);
+    yinc = -inc;
+  } else {
+    // upper
+    ystart = p.y + size / 2;
+    yinc = inc;
   }
-  ImGui::Dummy(ImVec2((size + spacing) * cols, (size + spacing) * rows));
+
+  float xstart, xinc;
+  if (config.start & 2) {
+    // right
+    xstart = p.x + size / 2 + inc * (cols - 1);
+    xinc = -inc;
+  } else {
+    // left
+    xstart = p.x + size / 2;
+    xinc = inc;
+  }
+
+  float x = xstart, y = ystart;
+  if (config.order == LEDConfig::RowMajor) {
+    // row major
+    int row = 1;
+    for (int i = 0; i < numValues; ++i) {
+      if (i >= (row * cols)) {
+        ++row;
+        if (config.serpentine) {
+          x -= xinc;
+          xinc = -xinc;
+        } else {
+          x = xstart;
+        }
+        y += yinc;
+      }
+      if (values[i] > 0)
+        drawList->AddRectFilled(ImVec2(x, y), ImVec2(x + size, y + size),
+                                colors[values[i] - 1]);
+      else if (values[i] < 0)
+        drawList->AddRect(ImVec2(x, y), ImVec2(x + size, y + size),
+                          colors[-values[i] - 1], 0.0f, 0, 1.0);
+      x += xinc;
+    }
+  } else {
+    // column major
+    int col = 1;
+    for (int i = 0; i < numValues; ++i) {
+      if (i >= (col * rows)) {
+        ++col;
+        if (config.serpentine) {
+          y -= yinc;
+          yinc = -yinc;
+        } else {
+          y = ystart;
+        }
+        x += xinc;
+      }
+      if (values[i] > 0)
+        drawList->AddRectFilled(ImVec2(x, y), ImVec2(x + size, y + size),
+                                colors[values[i] - 1]);
+      else if (values[i] < 0)
+        drawList->AddRect(ImVec2(x, y), ImVec2(x + size, y + size),
+                          colors[-values[i] - 1], 0.0f, 0, 1.0);
+      y += yinc;
+    }
+  }
+
+  ImGui::Dummy(ImVec2(inc * cols, inc * rows));
 }
 
 }  // namespace halsimgui
diff --git a/simulation/halsim_gui/src/main/native/cpp/PDPGui.cpp b/simulation/halsim_gui/src/main/native/cpp/PDPGui.cpp
index 038046e..da29ac3 100644
--- a/simulation/halsim_gui/src/main/native/cpp/PDPGui.cpp
+++ b/simulation/halsim_gui/src/main/native/cpp/PDPGui.cpp
@@ -8,6 +8,7 @@
 #include "PDPGui.h"
 
 #include <cstdio>
+#include <memory>
 
 #include <hal/Ports.h>
 #include <imgui.h>
@@ -21,6 +22,7 @@
   bool hasAny = false;
   static int numPDP = HAL_GetNumPDPModules();
   static int numChannels = HAL_GetNumPDPChannels();
+  static auto channelCurrents = std::make_unique<double[]>(numChannels);
   ImGui::PushItemWidth(ImGui::GetFontSize() * 13);
   for (int i = 0; i < numPDP; ++i) {
     if (HALSIM_GetPDPInitialized(i)) {
@@ -42,6 +44,7 @@
           HALSIM_SetPDPVoltage(i, volts);
 
         // channel currents; show as two columns laid out like PDP
+        HALSIM_GetPDPAllCurrents(i, channelCurrents.get());
         ImGui::Text("Channel Current (A)");
         ImGui::Columns(2, "channels", false);
         for (int left = 0, right = numChannels - 1; left < right;
@@ -49,13 +52,13 @@
           double val;
 
           std::snprintf(name, sizeof(name), "[%d]", left);
-          val = HALSIM_GetPDPCurrent(i, left);
+          val = channelCurrents[left];
           if (ImGui::InputDouble(name, &val))
             HALSIM_SetPDPCurrent(i, left, val);
           ImGui::NextColumn();
 
           std::snprintf(name, sizeof(name), "[%d]", right);
-          val = HALSIM_GetPDPCurrent(i, right);
+          val = channelCurrents[right];
           if (ImGui::InputDouble(name, &val))
             HALSIM_SetPDPCurrent(i, right, val);
           ImGui::NextColumn();
diff --git a/simulation/halsim_gui/src/main/native/cpp/PWMGui.cpp b/simulation/halsim_gui/src/main/native/cpp/PWMGui.cpp
index 8303f04..430502d 100644
--- a/simulation/halsim_gui/src/main/native/cpp/PWMGui.cpp
+++ b/simulation/halsim_gui/src/main/native/cpp/PWMGui.cpp
@@ -9,9 +9,11 @@
 
 #include <cstdio>
 #include <cstring>
+#include <memory>
 
 #include <hal/Ports.h>
 #include <imgui.h>
+#include <mockdata/AddressableLEDData.h>
 #include <mockdata/PWMData.h>
 
 #include "HALSimGui.h"
@@ -20,6 +22,19 @@
 
 static void DisplayPWMs() {
   bool hasOutputs = false;
+  static const int numPWM = HAL_GetNumPWMChannels();
+  static const int numLED = HAL_GetNumAddressableLEDs();
+  static auto ledMap = std::make_unique<int[]>(numPWM);
+
+  std::memset(ledMap.get(), 0, numPWM * sizeof(ledMap[0]));
+
+  for (int i = 0; i < numLED; ++i) {
+    if (HALSIM_GetAddressableLEDInitialized(i)) {
+      int channel = HALSIM_GetAddressableLEDOutputPort(i);
+      if (channel >= 0 && channel < numPWM) ledMap[channel] = i + 1;
+    }
+  }
+
   // struct History {
   //  History() { std::memset(data, 0, 90 * sizeof(float)); }
   //  History(const History&) = delete;
@@ -30,7 +45,6 @@
   //};
   // static std::vector<std::unique_ptr<History>> history;
   bool first = true;
-  static const int numPWM = HAL_GetNumPWMChannels();
   for (int i = 0; i < numPWM; ++i) {
     if (HALSIM_GetPWMInitialized(i)) {
       hasOutputs = true;
@@ -42,8 +56,12 @@
 
       char name[32];
       std::snprintf(name, sizeof(name), "PWM[%d]", i);
-      float val = HALSimGui::AreOutputsDisabled() ? 0 : HALSIM_GetPWMSpeed(i);
-      ImGui::Value(name, val, "%0.3f");
+      if (ledMap[i] > 0) {
+        ImGui::Text("%s: LED[%d]", name, ledMap[i] - 1);
+      } else {
+        float val = HALSimGui::AreOutputsDisabled() ? 0 : HALSIM_GetPWMSpeed(i);
+        ImGui::Value(name, val, "%0.3f");
+      }
 
       // lazily build history storage
       // if (static_cast<unsigned int>(i) > history.size())
diff --git a/simulation/halsim_gui/src/main/native/cpp/TimingGui.cpp b/simulation/halsim_gui/src/main/native/cpp/TimingGui.cpp
new file mode 100644
index 0000000..9897a7a
--- /dev/null
+++ b/simulation/halsim_gui/src/main/native/cpp/TimingGui.cpp
@@ -0,0 +1,60 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2019 FIRST. All Rights Reserved.                             */
+/* Open Source Software - may be 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 "TimingGui.h"
+
+#include <cstdio>
+#include <cstring>
+#include <vector>
+
+#include <hal/HALBase.h>
+#include <imgui.h>
+#include <mockdata/MockHooks.h>
+#include <mockdata/NotifierData.h>
+
+#include "HALSimGui.h"
+
+using namespace halsimgui;
+
+static void DisplayTiming() {
+  int32_t status = 0;
+  uint64_t curTime = HAL_GetFPGATime(&status);
+
+  if (ImGui::Button("Run")) HALSIM_ResumeTiming();
+  ImGui::SameLine();
+  if (ImGui::Button("Pause")) HALSIM_PauseTiming();
+  ImGui::SameLine();
+  ImGui::PushButtonRepeat(true);
+  if (ImGui::Button("Step")) {
+    HALSIM_PauseTiming();
+    uint64_t nextTimeout = HALSIM_GetNextNotifierTimeout();
+    if (nextTimeout != UINT64_MAX) HALSIM_StepTiming(nextTimeout - curTime);
+  }
+  ImGui::PopButtonRepeat();
+  ImGui::PushItemWidth(ImGui::GetFontSize() * 4);
+  ImGui::LabelText("FPGA Time", "%.3f", curTime / 1000000.0);
+  ImGui::PopItemWidth();
+
+  static std::vector<HALSIM_NotifierInfo> notifiers;
+  int32_t num = HALSIM_GetNotifierInfo(notifiers.data(), notifiers.size());
+  if (static_cast<uint32_t>(num) > notifiers.size()) {
+    notifiers.resize(num);
+    HALSIM_GetNotifierInfo(notifiers.data(), notifiers.size());
+  }
+  if (num > 0) ImGui::Separator();
+  ImGui::PushItemWidth(ImGui::GetFontSize() * 4);
+  for (int32_t i = 0; i < num; ++i)
+    ImGui::LabelText(notifiers[i].name, "%.3f",
+                     notifiers[i].timeout / 1000000.0);
+  ImGui::PopItemWidth();
+}
+
+void TimingGui::Initialize() {
+  HALSimGui::AddWindow("Timing", DisplayTiming,
+                       ImGuiWindowFlags_AlwaysAutoResize);
+  HALSimGui::SetDefaultWindowPos("Timing", 5, 150);
+}
diff --git a/simulation/halsim_gui/src/main/native/cpp/TimingGui.h b/simulation/halsim_gui/src/main/native/cpp/TimingGui.h
new file mode 100644
index 0000000..49f33cc
--- /dev/null
+++ b/simulation/halsim_gui/src/main/native/cpp/TimingGui.h
@@ -0,0 +1,17 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2019 FIRST. All Rights Reserved.                             */
+/* Open Source Software - may be modified and 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 halsimgui {
+
+class TimingGui {
+ public:
+  static void Initialize();
+};
+
+}  // namespace halsimgui
diff --git a/simulation/halsim_gui/src/main/native/cpp/main.cpp b/simulation/halsim_gui/src/main/native/cpp/main.cpp
index c049d1c..d5e0b16 100644
--- a/simulation/halsim_gui/src/main/native/cpp/main.cpp
+++ b/simulation/halsim_gui/src/main/native/cpp/main.cpp
@@ -9,6 +9,7 @@
 #include <wpi/raw_ostream.h>
 
 #include "AccelerometerGui.h"
+#include "AddressableLEDGui.h"
 #include "AnalogGyroGui.h"
 #include "AnalogInputGui.h"
 #include "AnalogOutGui.h"
@@ -23,6 +24,7 @@
 #include "RoboRioGui.h"
 #include "SimDeviceGui.h"
 #include "SolenoidGui.h"
+#include "TimingGui.h"
 
 using namespace halsimgui;
 
@@ -32,6 +34,7 @@
 #endif
     int HALSIM_InitExtension(void) {
   HALSimGui::Add(AccelerometerGui::Initialize);
+  HALSimGui::Add(AddressableLEDGui::Initialize);
   HALSimGui::Add(AnalogGyroGui::Initialize);
   HALSimGui::Add(AnalogInputGui::Initialize);
   HALSimGui::Add(AnalogOutGui::Initialize);
@@ -45,6 +48,7 @@
   HALSimGui::Add(RoboRioGui::Initialize);
   HALSimGui::Add(SimDeviceGui::Initialize);
   HALSimGui::Add(SolenoidGui::Initialize);
+  HALSimGui::Add(TimingGui::Initialize);
 
   wpi::outs() << "Simulator GUI Initializing.\n";
   if (!HALSimGui::Initialize()) return 0;
diff --git a/simulation/halsim_gui/src/main/native/include/ExtraGuiWidgets.h b/simulation/halsim_gui/src/main/native/include/ExtraGuiWidgets.h
index 11d83ba..7374cac 100644
--- a/simulation/halsim_gui/src/main/native/include/ExtraGuiWidgets.h
+++ b/simulation/halsim_gui/src/main/native/include/ExtraGuiWidgets.h
@@ -12,6 +12,33 @@
 namespace halsimgui {
 
 /**
+ * DrawLEDs() configuration for 2D arrays.
+ */
+struct LEDConfig {
+  /**
+   * Whether the major order is serpentined (e.g. the first row goes left to
+   * right, the second row right to left, the third row left to right, and so
+   * on).
+   */
+  bool serpentine = false;
+
+  /**
+   * The input array order (row-major or column-major).
+   */
+  enum Order { RowMajor = 0, ColumnMajor } order = RowMajor;
+
+  /**
+   * The starting location of the array (0 location).
+   */
+  enum Start {
+    UpperLeft = 0,
+    LowerLeft,
+    UpperRight,
+    LowerRight
+  } start = UpperLeft;
+};
+
+/**
  * Draw a 2D array of LEDs.
  *
  * Values are indices into colors array.  Positive values are filled (lit),
@@ -27,8 +54,10 @@
  *             if 0, defaults to 1/2 of font size
  * @param spacing spacing between each LED (both horizontal and vertical);
  *                if 0, defaults to 1/3 of font size
+ * @param config 2D array configuration
  */
-void DrawLEDs(int* values, int numValues, int cols, const ImU32* colors,
-              float size = 0.0f, float spacing = 0.0f);
+void DrawLEDs(const int* values, int numValues, int cols, const ImU32* colors,
+              float size = 0.0f, float spacing = 0.0f,
+              const LEDConfig& config = LEDConfig{});
 
 }  // namespace halsimgui
diff --git a/simulation/halsim_gui/src/test/native/cpp/main.cpp b/simulation/halsim_gui/src/test/native/cpp/main.cpp
index ba0d9b0..c6b6c58 100644
--- a/simulation/halsim_gui/src/test/native/cpp/main.cpp
+++ b/simulation/halsim_gui/src/test/native/cpp/main.cpp
@@ -1,17 +1,17 @@
-/*----------------------------------------------------------------------------*/

-/* Copyright (c) 2015-2019 FIRST. All Rights Reserved.                        */

-/* Open Source Software - may be 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;

-}

+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2019 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be 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/HALBase.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/simulation/halsim_print/src/dev/native/cpp/main.cpp b/simulation/halsim_print/src/dev/native/cpp/main.cpp
index d9f92e9..eb9eef1 100644
--- a/simulation/halsim_print/src/dev/native/cpp/main.cpp
+++ b/simulation/halsim_print/src/dev/native/cpp/main.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018 FIRST. All Rights Reserved.                             */
+/* Copyright (c) 2018-2019 FIRST. All Rights Reserved.                        */
 /* Open Source Software - may be modified and shared by FRC teams. The code   */
 /* must be accompanied by the FIRST BSD license file in the root directory of */
 /* the project.                                                               */
@@ -8,7 +8,7 @@
 #include <chrono>
 #include <thread>
 
-#include <hal/HAL.h>
+#include <hal/HALBase.h>
 
 int main() {
   HAL_Initialize(500, 0);
diff --git a/simulation/lowfi_simulation/build.gradle b/simulation/lowfi_simulation/build.gradle
index d86e4d6..e6e8143 100644
--- a/simulation/lowfi_simulation/build.gradle
+++ b/simulation/lowfi_simulation/build.gradle
@@ -30,16 +30,6 @@
 
     project(':').libraryBuild.dependsOn build
 
-    ext {
-        chipObjectComponents = ["$nativeName".toString(), "${nativeName}Dev".toString(), "${nativeName}Base".toString(),
-                                "${nativeName}Test".toString()]
-        netCommComponents = ["$nativeName".toString(), "${nativeName}Dev".toString(), "${nativeName}Base".toString(),
-                             "${nativeName}Test".toString()]
-        useNiJava = false
-    }
-
-    apply from: "${rootDir}/shared/nilibraries.gradle"
-
     nativeUtils.exportsConfigs {
         lowfi_sim {
             x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
@@ -125,6 +115,9 @@
                     project(':hal').addHalDependency(it, 'shared')
                     lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
                     lib library: nativeName, linkage: 'shared'
+                    if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
+                        nativeUtils.useRequiredLibrary(it, 'netcomm_shared', 'chipobject_shared', 'visa_shared', 'ni_runtime_shared')
+                    }
                 }
             }
         }
@@ -137,6 +130,9 @@
                 lib project: ':cameraserver', library: 'cameraserver', linkage: 'shared'
                 lib project: ':wpilibc', library: 'wpilibc', linkage: 'shared'
                 lib library: nativeName, linkage: 'shared'
+                if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
+                    nativeUtils.useRequiredLibrary(it, 'netcomm_shared', 'chipobject_shared', 'visa_shared', 'ni_runtime_shared')
+                }
             }
         }
     }
diff --git a/simulation/lowfi_simulation/publish.gradle b/simulation/lowfi_simulation/publish.gradle
index 9a3204e..1fa3aaf 100644
--- a/simulation/lowfi_simulation/publish.gradle
+++ b/simulation/lowfi_simulation/publish.gradle
@@ -7,8 +7,8 @@
 def outputsFolder = file("$project.buildDir/outputs")
 
 task cppSourcesZip(type: Zip) {
-    destinationDir = outputsFolder
-    baseName = zipBaseName
+    destinationDirectory = outputsFolder
+    archiveBaseName = zipBaseName
     classifier = "sources"
 
     from(licenseFile) {
@@ -21,8 +21,8 @@
 }
 
 task cppHeadersZip(type: Zip) {
-    destinationDir = outputsFolder
-    baseName = zipBaseName
+    destinationDirectory = outputsFolder
+    archiveBaseName = zipBaseName
     classifier = "headers"
 
     from(licenseFile) {
diff --git a/simulation/lowfi_simulation/src/dev/native/cpp/main.cpp b/simulation/lowfi_simulation/src/dev/native/cpp/main.cpp
index 4dc5f43..eb83810 100644
--- a/simulation/lowfi_simulation/src/dev/native/cpp/main.cpp
+++ b/simulation/lowfi_simulation/src/dev/native/cpp/main.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2017-2019 FIRST. All Rights Reserved.                        */
 /* Open Source Software - may be modified and shared by FRC teams. The code   */
 /* must be accompanied by the FIRST BSD license file in the root directory of */
 /* the project.                                                               */
@@ -7,7 +7,7 @@
 
 #include <iostream>
 
-#include <hal/HAL.h>
+#include <hal/HALBase.h>
 
 int main() {
   std::cout << "Hello World" << std::endl;
diff --git a/simulation/lowfi_simulation/src/test/native/cpp/lowfisim/MotorEncoderSimulatorTest.cpp b/simulation/lowfi_simulation/src/test/native/cpp/lowfisim/MotorEncoderSimulatorTest.cpp
index 83e9ddc..9166de3 100644
--- a/simulation/lowfi_simulation/src/test/native/cpp/lowfisim/MotorEncoderSimulatorTest.cpp
+++ b/simulation/lowfi_simulation/src/test/native/cpp/lowfisim/MotorEncoderSimulatorTest.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018 FIRST. All Rights Reserved.                             */
+/* Copyright (c) 2018-2019 FIRST. All Rights Reserved.                        */
 /* Open Source Software - may be modified and shared by FRC teams. The code   */
 /* must be accompanied by the FIRST BSD license file in the root directory of */
 /* the project.                                                               */
@@ -49,7 +49,7 @@
   frc::sim::lowfi::MotorEncoderConnector connector(motorSim, encoderSim);
 
   talon.Set(0.5);
-  motorSim.Update(.02);
+  motorSim.Update(0.02);
   connector.Update();
 
   // Position
@@ -64,7 +64,7 @@
 TEST(MotorEncoderConnectorTest, TestWithDistancePerPulseFullSpeed) {
   frc::Talon talon{3};
   frc::Encoder encoder{3, 1};
-  encoder.SetDistancePerPulse(.001);
+  encoder.SetDistancePerPulse(0.001);
 
   frc::sim::lowfi::SimpleMotorModel motorModelSim(6000);
   frc::sim::lowfi::WpiMotorSim motorSim(3, motorModelSim);
@@ -88,7 +88,7 @@
 TEST(MotorEncoderConnectorTest, TestWithDistancePerPulseRealistic) {
   frc::Talon talon{3};
   frc::Encoder encoder{3, 1};
-  encoder.SetDistancePerPulse(.001);
+  encoder.SetDistancePerPulse(0.001);
 
   frc::sim::lowfi::SimpleMotorModel motorModelSim(6000);
   frc::sim::lowfi::WpiMotorSim motorSim(3, motorModelSim);
@@ -97,7 +97,7 @@
 
   talon.Set(0.5);
 
-  motorSim.Update(.02);
+  motorSim.Update(0.02);
   connector.Update();
 
   // Position
diff --git a/simulation/lowfi_simulation/src/test/native/cpp/lowfisim/motormodel/SimpleMotorModelSimulationTest.cpp b/simulation/lowfi_simulation/src/test/native/cpp/lowfisim/motormodel/SimpleMotorModelSimulationTest.cpp
index e60cf1e..21c5e7e 100644
--- a/simulation/lowfi_simulation/src/test/native/cpp/lowfisim/motormodel/SimpleMotorModelSimulationTest.cpp
+++ b/simulation/lowfi_simulation/src/test/native/cpp/lowfisim/motormodel/SimpleMotorModelSimulationTest.cpp
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018 FIRST. All Rights Reserved.                             */
+/* Copyright (c) 2018-2019 FIRST. All Rights Reserved.                        */
 /* Open Source Software - may be modified and shared by FRC teams. The code   */
 /* must be accompanied by the FIRST BSD license file in the root directory of */
 /* the project.                                                               */
@@ -13,7 +13,7 @@
 
   // Test forward voltage
   motorModelSim.SetVoltage(6);
-  motorModelSim.Update(.5);
+  motorModelSim.Update(0.5);
 
   EXPECT_DOUBLE_EQ(50, motorModelSim.GetPosition());
   EXPECT_DOUBLE_EQ(100, motorModelSim.GetVelocity());
@@ -26,7 +26,7 @@
   // Test negative voltage
   motorModelSim.Reset();
   motorModelSim.SetVoltage(-3);
-  motorModelSim.Update(.06);
+  motorModelSim.Update(0.06);
 
   EXPECT_DOUBLE_EQ(-3, motorModelSim.GetPosition());
   EXPECT_DOUBLE_EQ(-50, motorModelSim.GetVelocity());
diff --git a/simulation/lowfi_simulation/src/test/native/cpp/main.cpp b/simulation/lowfi_simulation/src/test/native/cpp/main.cpp
index 0e00efa..c6b6c58 100644
--- a/simulation/lowfi_simulation/src/test/native/cpp/main.cpp
+++ b/simulation/lowfi_simulation/src/test/native/cpp/main.cpp
@@ -1,11 +1,11 @@
 /*----------------------------------------------------------------------------*/
-/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Copyright (c) 2015-2019 FIRST. All Rights Reserved.                        */
 /* Open Source Software - may be 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 <hal/HALBase.h>
 
 #include "gtest/gtest.h"