Squashed 'third_party/allwpilib/' changes from 83f1860047..f1a82828fe

f1a82828fe [wpiutil] Add DataLog and DataLogManager Stop() (#5860)
2a04e12c6f [apriltag] AprilTagFieldLayout: Add accessors for origin and field dimensions (#5869)
33e0089afb Cleanup usages of std::function<void(void)> (#5864)
d06fa633d5 [build] Fix protobuf generation when building with make (#5867)
049732afb8 [cscore] Make camera connection logging clearer (#5866)
87f7c19f90 [wpimath] Make InterpolatingDoubleTreeMap constructor public (#5865)
6b53ef47cf [wpimath] Don't recreate TrapezoidProfile in ProfiledPIDController calculate() (#5863)
8a3a268ae6 [commands] Add finallyDo with zero-arg lambda (#5862)
1c35d42cd0 [wpilib] Pop diagnostic for deprecated function use (#5859)
ddc8db6c26 [wpimath] Add feedforward constant constructor to ElevatorSim (#5823)
c6aff2c431 [upstream_utils] Update to LLVM 17.0.4 (#5855)
a9c5b18a39 [build] Update OpenCV to 2024-4.8.0-2 (#5854)
9540b6922d [hal] Add CAN IDs for AndyMark and Vivid Hosting (#5852)
83a7d33c47 [glass] Improve display of protobuf/struct type strings (#5850)
a4a8ad9c75 [commands] Make Java SelectCommand generic (#5849)
9eecf2a456 [build] Add CMake option to build Java sources jars (#5768)
9536a311cb [wpilib] Add support for the PS5 DualSense controller (#5257)
8d5e6737fc [wpilibc] SolenoidSim: Add virtual destructor (#5848)
07e13d60a2 [ntcore] Fix write_impl (#5847)
1713386869 [wpiutil] ProtobufMessageDatabase: Fix out-of-order Add() rebuild (#5845)
35472f5fc9 [ntcore] Fix a use-after-free in client close (#5844)
ed168b522c [ntcore] Disable buf pool when asan is enabled (#5843)
3e7ba2cc6f [wpinet] WebSocket: Fix write behavior (#5841)
80c47da237 [sim] Disable the robot program when DS disconnects (#5818)
abe1cec90c [wpilib] Update Usage Reporting ResourceType from NI Libraries (#5842)
cdf981abba [glass] Fix position of data type in NT view (#5840)
04dcd80adb [build] Publish unit tests for examples (#5838)
49920234ac [build] Fix checkstyle rules to allow Windows paths (#5839)
366b715942 [wpilib] Fix SendableChooser test (#5835)
3ba501f947 [commands] Java: Fix CommandXboxController.leftTrigger() parameter order (#5831)
ec569a58ef [wpimath] Make KalmanTypeFilter interface public (#5830)
b91317fd36 [wpiutil] DataLog.addSchema(): Don't add into a set view (#5829)
2ab4fcbc24 [wpiutil] ProtobufMessageDatabase: Clear messages first (#5827)
98c14f1692 [wpimath] Add EKF/UKF u-y-R correct overload (#5832)
60bcdeded9 [ci] Disable java in sanitizer builds (#5833)
c87f8fd538 [commands] Add DeferredCommand (#5566)
ad80eb3a0b [ci] Update actions for comment-command (#5824)
c7d6ad5a0b [ntcore] WebSocketConnection: Use weak capture (#5822)
8a8e220792 [simgui] Add 'Invalid' option for AllianceStation (#5820)
cfc6a47f76 [sim] DS plugin: Fix off-by-one error when setting alliance station (#5819)
8efa586ace [ntcore] Don't check type string on publishing an entry (#5816)
23ea188e60 [glass] Add protobuf decode error log message (#5812)
928e87b4f4 [build] Add combined test meta-task (#5813)
63ef585d4b [wpiutil] Fix compilation of MathExtras.h on Windows with /sdl (#5809)
b03a7668f9 [build] Windows CMake/vcpkg fixes (#5807)
3f08bcde54 [hal] Fix HAL AllianceStation on rio (#5811)
196d963dc4 [ntcore] Fix off-by-one error in stream write (#5810)
f4cbcbc984 Fix typos (NFC) (#5804)
ec0f7fefb0 [myrobot] Update the myRobot JRE (#5805)
3d618bdbfd [wpiutil] Fix Java struct array unpacking (#5801)
1fa7445667 [ntcore] Check for valid client in incoming text and binary (#5799)
269b9647da [ci] Update JDK for combine step (#5794)
bee32f080e [docs] Add wpiunits to JavaDocs (#5793)
25dad5a531 [wpinet] TCPConnector_parallel: Don't use thread_local (#5791)
4a93581f1a [build] cmake: use default library type for libglassnt, libglass, wpigui, and imgui (#5797)
abb2857e03 [wpilib] Counter: Fix default distance per pulse, add distance and rate to C++ (#5796)
b14a61e1c0 [readme] Add link to QuickBuffers release page (#5795)
cf54d9ccb7 [wpiutil, ntcore] Add structured data support (#5391)
ecb7cfa9ef [wpimath] Add Exponential motion profile (#5720)
7c6fe56cf2 [ntcore] Fix crash on disconnect (#5788)
85147bf69e [wpinet] WebSocketSerializer: Fix UB (#5787)
244163acad [wpinet] uv::Stream::TryWrite(): Return 0 on EAGAIN (#5784)
820728503d [hal] Remove extra semicolon in RoboRioData (#5786)
45f307d87e [upstream_utils] Upgrade to LLVM 17.0.3 (#5785)
4ce4d63efc [wpilibj] Fix RobotBase.isSimulation() (#5783)
579007ceb3 [commands] Add requirements parameter to Commands.idle() (#5774)
3f3a169149 [wpilib] Make physics sim setState() functions public (#5779)
7501e4ac88 [wpilib] Close sim device in ADIS IMUs (#5776)
99630d2e78 [wpimath] Upgrade to EJML 0.43.1 (#5778)
02cbbc997d [wpimath] Make Vector-Vector binary operators return Vector (#5772)
ed93889e17 [examples] Fix typo in TimesliceRobot example name (#5773)
da70e4c262 [docs] Add jinja2 to CMake prerequisites (#5771)
e814595ea7 [wpimath] Add ChassisSpeeds.fromRobotRelativeSpeeds() (#5744)
f98c943445 [wpimath] LinearSystemId: Add DCMotorSystem overload (#5770)
b3eb64b0f7 [wpiutil] ct_string: Use inline namespace for literals (#5767)
7d9ba256c2 Revert "[build] Add CMake option to build Java source jars (#5756)" (#5766)
1f6492e3d8 [sysid] Update JSON library usage (#5765)
638f04f626 [wpiutil] Add protobuf to thirdparty sources (#5746)
210255bfff [wpiutil] Update json to 3.11.2 (#5680)
896772c750 [wpimath] Add DCMotor functions for Kraken X60 and Neo Vortex (#5759)
fd427f6c82 [wpimath] Fix hardcoded module count in SwerveDriveKinematics.resetHeading() (#5762)
c0b4c6cce6 [wpimath] Add overloads for Transform2d and Transform3d (#5757)
9a0aafd8ab [examples] Make swerve examples multiply desired module speeds by cosine of heading error (#5758)
1c724884ca [build] Add CMake option to build Java source jars (#5756)
5b0db6b93e [ci] Forward CI as well (#5755)
f8cbbbac12 [ci] Take 2 on passing GITHUB_REF (#5754)
b9944be09c [ci] Pass GITHUB_REF to docker container (#5753)
de5e4eda6c [build] Update apriltag, libssh, googletest for 2024 (#5752)
227e660e20 [upstream_utils] Upgrade to LLVM 17.0.2 (#5750)
36f94c9f21 [commands,romi,xrp] Add frcYear to vendordep (#5747)
741d166457 [glass] NT view: enhance array support (#5732)
1d23513945 [ntcore] Fix string array value comparison (#5745)
ff1849052e [commands] Make command scheduling order consistent (#5470)
58e8474368 [build] Disable armsimulation unit test (#5739)
fb07b0da49 [examples] Add XRP C++ Examples and Templates (#5743)
81893ad73d Run wpiformat with clang-format 17 (#5740)
faa1e665ba [wpimath] Add ElevatorFeedforward.calculate(currentV, nextV) overload (#5715)
a789632052 [build] Update to native utils 2024.3.1 (#5738)
8f60ab5182 [build] Update OpenCV to 2024-4.8.0-1 (#5737)
33243f982b [wpimath] Expand Quaternion class with additional operators (#5600)
420f2f7c80 [ntcore] Add RTT-only subprotocol (#5731)
2b63e35ded [ntcore] Fix moving outgoing queue to new period (#5735)
be939cb636 [ntcore] Fix notification of SetDefaultEntryValue (#5733)
69a54de202 [build] Update enterprise plugin (#5730)
fef03a3ff5 [commands] Clean up C++ includes after Requirements was added (#5719)
8b7c6852cf [ntcore] Networking improvements (#5659)
1d19e09ca9 [wpiutil] Set WPI_{UN}IGNORE_DEPRECATED to empty when all else fails (#5728)
58141d6eb5 [wpilib] Make BooleanEvent more consistent (#5436)
6576d9b474 [wpilib] SendableChooser: implement Sendable instead of NTSendable (#5718)
a4030c670f [build] Update to gradle 8.4, enable win arm builds (#5727)
0960f11eba [wpinet] Revert removal of uv_clock_gettime() (#5723)
cb1bd0a3be [wpiutil] Get more precise system time on Windows (#5722)
4831277ffe [wpigui] Fix loading a maximized window on second monitor (#5721)
3eb372c25a [wpiutil] SendableBuilder: Add PublishConst methods (#5158)
1fec8596a4 [ci] Fix -dirty version (#5716)
f7e47d03f3 [build] Remove unnecessary CMake config installs (#5714)
a331ed2374 [sysid] Add SysId (#5672)
8d2cbfce16 [wpiutil] DataLog: Stop logging if insufficient free space (#5699)
48facb9cef [ntcoreffi] Add DataLogManager (#5702)
aecbcb08fc [ntcore] Correctly start DataLog for existing publishers (#5703)
5e295dfbda [wpiutil] DataLog: Limit total buffer allocation (#5700)
c7c7e05d9d [ci] Unbreak combiner (#5698)
c92bad52cb [wpilib] DataLogManager: Use system time valid function (#5697)
d404af5f24 [wpilib] RobotController: Add isSystemTimeValid() (#5696)
e56f1a3632 [ci] Run combine but skip all steps (#5695)
8f5bcad244 [ci] Use sccache for cmake builds (#5692)
703dedc4a6 [ci] Upgrade get-cmake action to fix node12 deprecation warning (#5694)
c69a0d7504 [ci] Don't run example unit test that segfaults (#5693)
66358d103e Add menu items for online docs to GUI tools (#5689)
4be8384a76 [ci] Disable combine on PR builds (#5691)
90288f06a6 [ci] Fix Gradle disk space issues (#5688)
9e9583412e [wpigui] Make wpi::gui::OpenURL() fork the process first (#5687)
d4fcd80b7b [ci] Gradle: Use container only for build step (#5684)
7b70e66772 [outlineviewer] Fix thirdparty library include sorting (#5683)
5f651df5d5 [build] Clean up Gradle configs (#5685)
65b26738d5 Add CMakeSettings.json to gitignore (#5682)
d0305951ad Fix GitHub inline warnings (#5681)
e8d4a20331 [build][cmake] Fix windows tests and re-enable CI tests (#5674)
2b58bbde0b [xrp] Add Reflectance sensor and rangefinder classes (#5673)
dd5612fbee [json] Add forward definition header (#5676)
eab44534c3 [wpimath] Remove unused SmallString include (#5677)
5ab54ff760 Replace wpi::raw_istream with wpi::MemoryBuffer (#5675)
1b6ec5a95d [wpiutil] Upgrade to LLVM 17.0.1 (#5482)
07a0d22fe6 [build] Build examples in CMake CI (#5667)
97021f074a [build] Upgrade imgui and implot (#5668)
87ce1e3761 [build] Fix wpilibNewCommands CMake install (#5671)
6ef94de9b5 [wpimath] Add tests for ArmFeedforward and ElevatorFeedforward (#5663)
c395b29fb4 [wpinet] Add WebSocket::TrySendFrames() (#5607)
c4643ba047 [romi/xrp] Fix version typo in vendordep json (#5664)
51dcb8b55a [examples] Make Romi/XRP Examples use appropriate vendordeps (#5665)
daf7702007 [build] Test each example in a new environment (#5662)
e67df8c180 [wpilib] Const-qualify EncoderSim getters (#5660)
7be290147c [wpiutil] Refactor SpanMatcher and TestPrinters from ntcore (#5658)
9fe258427a [commands] Add proxy factory to Commands (#5603)
633c5a8a22 [commands] Add C++ Requirements struct (#5504)
b265a68eea [commands] Add interruptor parameter to onCommandInterrupt callbacks (#5461)
e93c233d60 [ntcore] Compute Value memory size when creating value (#5657)
5383589f99 [wpinet] uv::Request: Return shared_ptr from Release() (#5656)
40b552be4a [wpinet] uv::Stream: Return error from TryWrite() (#5655)
202a75fe08 [wpinet] RequestImpl: Avoid infinite loop in shared_from_this() (#5654)
8896515eb7 [wpinet] uv::Buffer: Add bytes() accessor (#5653)
ae59a2fba2 [wpinet] uv::Error: Change default error to 0 (#5652)
3b51ecc35b [wpiutil] SpanExtras: Add take_back and take_front (#5651)
17f1062885 Replace std::snprintf() with wpi::format_to_n_c_str() (#5645)
bb39900353 [romi/xrp] Add Romi and XRP Vendordeps (#5644)
cb99517838 [build] cmake: Use default install location on windows for dlls (#5580)
25b0622d4c [build] Add Windows CMake CI (#5516)
34e7849605 Add warning to development builds instructions (NFC) (#5646)
e9e611c9d8 [cameraserver] Remove CameraServer.SetSize() (#5650)
94f58cc536 [wpilib] Remove Compressor.Enabled() (#5649)
4da5aee88a [wpimath] Remove SlewRateLimiter 2 argument constructor (#5648)
2e3ddf5502 Update versions in development builds instructions to 2024 (#5647)
19a8850fb1 [examples] Add TimesliceRobot templates (#3683)
9047682202 [sim] Add XRP-specific plugin (#5631)
575348b81c [wpilib] Use IsSimulation() consistently (#3534)
12e2043b77 [wpilib] Clean up Notifier (#5630)
4bac4dd0f4 [wpimath] Move PIDController from frc2 to frc namespace (#5640)
494cfd78c1 [wpiutil] Fix deprecation warning in LLVM for C++23 (#5642)
43a727e868 [apriltag] Make loadAprilTagFieldLayout throw an unchecked exception instead (#5629)
ad4b017321 [ci] Use Ninja for faster builds (#5626)
4f2114d6f5 Fix warnings from GCC 13 release build (#5637)
e7e927fe26 [build] Also compress debug info for CMake RelWithDebInfo build type (#5638)
205a40c895 [build] Specify zlib for debug info compression (#5636)
707444f000 [apriltag] Suppress -Wtype-limits warning in asserts from GCC 13 (#5635)
3b79cb6ed3 [commands] Revert SubsystemBase deprecation/removal (#5634)
bc7f23a632 [build] Compress Linux debug info (#5633)
57b2d6f254 [build] Update to image 2024 v1.0 (#5625)
339ef1ea39 [wpilib] DataLogManager: Warn user if logging to RoboRIO 1 internal storage (#5617)
7a9a901a73 [build] Fix cmake config files (#5624)
298f8a6e33 [wpilib] Add Mechanism2d tests and make Java impl match C++ (#5527)
d7ef817bae [apriltag] Update apriltag library (#5619)
c3fb31fd0e [docs] Switch to Java 17 api docs (#5613)
bd64f81cf9 [build] Run Google tests in release mode in CI (#5615)
66e6bd81ea [wpimath] Cleanup wpimath/algorithms.md (NFC) (#5621)
4fa56fd884 [build] Add missing find_dependency call (#5623)
f63d958995 [build] Update to native utils 2024.2.0 (#5601)
a9ab08f48b [wpimath] Rename ChassisSpeeds.fromDiscreteSpeeds() to discretize() (#5616)
8e05983a4a [wpimath] Add math docs to plant inversion feedforward internals (NFC) (#5618)
3a33ce918b [ntcore] Add missing StringMap include (#5620)
a6157f184d [wpiutil] timestamp: Add ShutdownNowRio (#5610)
e9f612f581 [build] Guard policy setting for CMake versions below 3.24 (#5612)
1a6df6fec6 [wpimath] Fix DARE Q decomposition (#5611)
9b3f7fb548 [build] Exclude IntelliJ folders from spotless XML (#5602)
814f18c7f5 [wpimath] Fix computation of C for DARE (A, C) detectability check (#5609)
ac23f92451 [hal] Add GetTeamNumber (#5596)
a750bee54d [wpimath] Use std::norm() in IsStabilizable() (#5599)
8e2465f8a0 [wpimath] Add arithmetic functions to wheel speeds classes (#5465)
10d4f5b5df [wpimath] Clean up notation in DARE precondition docs (#5595)
b2dd59450b [hal] Fix unfinished/incorrect GetCPUTemp functions (#5598)
99f66b1e24 [wpimath] Replace frc/EigenCore.h typedefs with Eigen's where possible (#5597)
383289bc4b [build] Make custom CMake macros use lowercase (#5594)
45e7720ec1 [build] Add error message when downloading files in CMake (#5593)
4e0d785356 [wpimath] ChassisSpeeds: document that values aren't relative to the robot (NFC) (#5551)
3c04580a57 [commands] ProxyCommand: Use inner command name in unique_ptr constructor (#5570)
cf19102c4a [commands] SelectCommand: Fix leakage and multiple composition bug (#5571)
171375f440 [ntcoreffi] Link to NI libraries (#5589)
89add5d05b Disable flaky tests (#5591)
a8d4b162ab [ntcore] Remove RPC manual tests (#5590)
39a73b5b58 [commands] C++: Add CommandPtr supplier constructor to ProxyCommand (#5572)
36d514eae7 [commands] Refactor C++ ScheduleCommand to use SmallSet (#5568)
52297ffe29 [commands] Add idle command (#5555)
67043a8eeb [wpimath] Add angular jerk unit (#5582)
51b0fb1492 [wpimath] Fix incorrect header inclusion in angular_acceleration.h (#5587)
b7657a8e28 [wpimath] Split WPIMathJNI into logical chunks (#5552)
ea17f90f87 [build] Fix tool builds with multiple arm platforms installed (#5586)
f1d7b05723 [wpimath] Clean up unit formatter (#5584)
d7264ff597 Replace wpi::errs() usage with fmtlib (#5560)
ab3bf39e0e [wpiutil] Upgrade to fmt 10.1.1 (#5585)
165ebe4c79 Upgrade to fmt 10.1.0 (#5326)
8e2a7fd306 Include thirdparty libraries with angle brackets (#5578)
e322ab8e46 [wpimath] Fix docs for DARE ABQRN stabilizability check (NFC) (#5579)
360fb835f4 [upstream_utils] Handle edge case in filename matches (#5576)
9d86624c00 [build] Fix CMake configure warnings (#5577)
969979d6c7 [wpiutil] Update to foonathan memory 0.7-3 (#5573)
0d2d989e84 [wpimath] Update to gcem 1.17.0 (#5575)
cf86af7166 [wpiutil] Update to mpack 1.1.1 (#5574)
a0c029a35b [commands] Fix dangling SelectCommand documentation (NFC) (#5567)
349141b91b [upstream_utils] Document adding a patch (NFC) (#5432)
7889b35b67 [wpimath] Add RamseteController comparison to LTV controller docs (NFC) (#5559)
b3ef536677 [build] Ignore nt/sim json files in spotless (#5565)
ed895815b5 [build] Compile Java with UTF-8 encoding (#5564)
2e4ad35e36 [wpiutil] jni_util: Add JSpan and CriticalJSpan (#5554)
8f3d6a1d4b [wpimath] Remove discretizeAQTaylor() (#5562)
7c20fa1b18 [wpimath] Refactor DARE tests to reduce RAM usage at compile time (#5557)
89e738262c [ntcore] Limit buffer pool size to 64KB per connection (#5485)
96f7fa662e Upgrade Maven dependencies (#5553)
7a2d336d52 [wpinet] Leak multicast handles during windows shutdown (#5550)
f9e2757d8f [wpimath] Use JDoubleArrayRef in all JNI functions (#5546)
0cf6e37dc1 [wpimath] Make LTV controller constructors use faster DARE solver (#5543)
6953a303b3 [build] Fix the windows build with fmt (#5544)
7a37e3a496 [wpimath] Correct Rotation3d::RotateBy doc comment (NFC) (#5541)
186b409e16 [wpimath] Remove internal Eigen header include (#5539)
03764dfe93 [wpimath] Add static matrix support to DARE solver (#5536)
394cfeadbd [wpimath] Use SDA algorithm instead of SSCA for DARE solver (#5526)
a4b7fde767 [wpilib] Add mechanism specific SetState overloads to physics sims (#5534)
8121566258 [wpimath] Fix CoordinateSystem.convert() Transform3d overload (#5532)
b542e01a0b [glass] Fix array crash when clearing existing workspace (#5535)
e2e1b763b2 [wpigui] Fix PFD file dialogs not closing after window closing (#5530)
86d7bbc4e4 [examples] Add Java Examples and Templates for the XRP (#5529)
e8b5d44752 [wpimath] Make Java Quaternion use doubles instead of Vector (#5525)
38c198fa64 [myRobot] Add apriltags to myRobot build (#5528)
00450c3548 [wpimath] Upgrade to EJML 0.42 (#5531)
faf3cecd83 [wpimath] Don't copy Matrix and underlying storage in VecBuilder (#5524)
6b896a38dc [build] Don't enforce WITH_FLAT_INSTALL with MSVC (part 2) (#5517)
c01814b80e [wpiutil] Add C API for DataLog (#5509)
b5bd0771eb [wpimath] Document extrinsic vs intrinsic rotations (NFC) (#5508)
84ed8aec05 [build] Don't enforce WITH_FLAT_INSTALL with MSVC (#5515)
999f677d8c [ntcoreffi] Add WPI_Impl_SetupNowRio to exported symbols (#5510)
338f37d302 Fix header sorting of libssh (#5507)
75cbd9d6d0 [glass] Add background color selector to glass plots (#5506)
e2c190487b [examples] Add flywheel bang-bang controller example (#4071)
c52dad609e [wpinet] WebSocket: Send pong in response to ping (#5498)
e2d17a24a6 [hal] Expose power rail disable and cpu temp functionality (#5477)
3ad5d2e42d [hal,wpiutil] Use HMB for FPGA Timestamps (#5499)
b46a872494 [ntcore] Remove pImpl from implementation (#5480)
d8c59ccc71 [wpimath] Add tests for MathUtil clamp() and interpolate() (#5501)
0552c8621d [glass,ov] Improve Glass and OutlineViewer title bar message (#5502)
90e37a129f [wpiutil,wpimath] Add generic InterpolatingTreeMap (#5372)
d83a6edc20 [wpilib] Update GetMatchTime docs and units (#5232)
6db2c42966 [wpimath] Trajectory: Throw on empty lists of States (#5497)
21439b606c [wpimath] Disallow LTV controller max velocities above 15 m/s (#5495)
7496e0d208 [ntcore] Value: More efficiently store arrays (#5484)
0c93aded8a [wpimath] Change kinematics.ToTwist2d(end - start) to kinematics.ToTwist2d(start, end) (#5493)
815a8403e5 [wpimath] Give infeasible trajectory constraints a better exception message (#5492)
35a8b129d9 [wpimath] Add RotateBy() function to pose classes (#5491)
26d6e68c8f [upstream_utils] Add GCEM to CI (#5483)
6aa469ae45 [wpilib] Document how to create LinearSystem object for physics sim classes (NFC) (#5488)
a01b6467d3 [wpimath] Link to docs on LQR and KF tolerances (#5486)
d814f1d123 [wpimath] Fix copy-paste error from Pose2d docs (NFC) (#5490)
98f074b072 [wpimath] Add folder prefix to geometry includes (#5489)
e9858c10e9 [glass] Add tooltips for NT settings (#5476)
12dda24f06 [examples] Fix C robot template not correctly looping (#5474)
fc75d31755 [apriltag] Update apriltaglib (#5475)
a95994fff6 [wpiutil] timestamp: Call FPGA functions directly (#5235)
2ba8fbb6f4 [wpimath] Improve documentation for SwerveModulePosition::operator- (#5468)
b8cdf97621 [build] Prepare for Windows arm64 builds (#5390)
552f4b76b5 [wpimath] Add FOC-enabled Falcon constants to the DCMotor class (#5469)
1938251436 [examples] Add Feedforward to ElevatorProfiledPid (#5300)
873c2a6c10 [examples] Update ElevatorTrapezoidProfile example (#5466)
99b88be4f3 [wpilib] Reduce usage of NTSendable (#5434)
d125711023 [hal] Fix Java REVPH faults bitfield (take 2) (#5464)
c3fab7f1f2 [ntcore] Don't update timestamp when value is unchanged (#5356)
5ec7f18bdc [wpilib] EventLoop docs: Remove BooleanEvent references (NFC) (#5463)
c065ae1fcf [wpiunits] Add subproject for a Java typesafe unit system (#5371)
44acca7c00 [wpiutil] Add ClassPreloader (#5365)
88b11832ec [hal] Fix Java REVPH faults bitfield (#5148)
fb57d82e52 [ntcore] Enhance Java raw value support
3a6e40a44b [wpiutil] Enhance DataLog Java raw value support
8dae5af271 [wpiutil] Add compile-time string utilities (ct_string) (#5462)
fc56f8049a [wpilib] DriverStation: Change alliance station to use optional (#5229)
ef155438bd [build] Consume libuv via cmake config instead of via pkg-config (#5438)
86e91e6724 [wpimath] Refactor TrapezoidProfile API (#5457)
72a4543493 [wpilib] DutyCycleEncoderSim: Expand API (#5443)
657338715d [wpimath] Add ChassisSpeeds method to fix drifting during compound swerve drive maneuvers (#5425)
1af224c21b Add missing <functional> includes (#5459)
0b91ca6d5a [wpilib] SendableChooser: Add onChange listener (#5458)
6f7cdd460e [wpimath] Pose3d: Switch to JNI for exp and log (#5444)
c69e34c80c [wpimath] ChassisSpeeds: Add arithmetic functions (#5293)
335e7dd89d [wpilib] Simulation: Add ctor parameter to set starting state of mechanism sims (#5288)
14f30752ab [wpilib] Deprecate Accelerometer and Gyro interfaces (#5445)
70b60e3a74 [commands] Trigger: Fix method names in requireNonNullParam (#5454)
593767c8c7 [wpimath] Improve Euler angle calculations in gimbal lock (#5437)
daf022d3da [build] Make devImplementation inherit from implementation (#5450)
9b8d90b852 [examples] Convert the unitless joystick inputs to actual physical units (#5451)
1f6428ab63 [ntcore] Fix undefined comparison behavior when array is empty (#5448)
17eb9161cd Update code owners for removal of old commands (#5447)
3c4b58ae1e [wpinet] Upgrade to libuv 1.46.0 (#5446)
aaea85ff16 [commands] Merge CommandBase into Command and SubsystemBase into Subsystem (#5392)
7ac932996a [ci] Use PAT for workflow dispatch (#5442)
efe1987e8b [ci] Trigger pages repo workflow (#5441)
828bc5276f [wpiutil] Upgrade to LLVM 16.0.6 (#5435)
701df9eb87 [ci] Change documentation publish to single-commit (#5440)
e5452e3f69 [wpiutil] Add WPICleaner and an example how to use it (#4850)
7a099cb02a [commands] Remove deprecated classes and functions (#5409)
b250a03944 [wpilib] Add function to wait for DS Connection (#5230)
a6463ed761 [wpiutil] Fix unused variable warning in release build (#5430)
f031513470 [ntcore] NetworkTable::GetSubTables(): Remove duplicates (#5076)
f8e74e2f7c [hal] Unify PWM simulation Speed, Position, and Raw (#5277)
fd5699b240 Remove references to Drake (#5427)
e2d385d80a [build] cmake: Respect USE_SYSTEM_FMTLIB (#5429)
d37f990ce3 [hal] Fix HAL Relay/Main doc module (NFC) (#5422)
a7a8b874ac [docs] Expand HAL_ENUM in doxygen docs (#5421)
3a61deedde [wpimath] Rotation2d: Only use gcem::hypot when constexpr evaluated (#5419)
96145de7db [examples] Fix formatting (NFC) (#5420)
fffe6a7b9a [examples] Improve Pneumatics example coverage in Solenoid and RapidReactCmdBot examples (#4998)
6b5817836d [wpimath] Add tolerance for some tests (#5416)
3233883f3e [cscore] Fix warnings on macos arm (#5415)
c4fc21838f [commands] Add ConditionalCommand getInterruptionBehavior (#5161)
89fc51f0d4 Add tests for SendableChooser and Command Sendable functionality (#5179)
663bf25aaf [docs] Generate docs for symbols in __cplusplus (#5412)
fe32127ea8 [command] Clean up Command doc comments (NFC) (#5321)
c1a01569b4 [wpilib][hal] PWM Raw using microseconds (#5283)
1fca519fb4 [wpiutil] Remove remnants of ghc fs and tcb_span libraries (#5411)
90602cc135 [github] Update issue template to collect more project info (#5090)
34412ac57e [build] Exclude files in bin from Spotless (#5410)
61aa60f0e3 [wpilib] Add robot callback that is called when the DS is initially connected (#5231)
ebae341a91 [commands] Add test for subsystem registration and periodic (#5408)
5d3a133f9f Remove spaces in NOLINT comments (#5407)
3a0e484691 [wpimath] Fix clang-tidy warnings (#5403)
eb3810c765 [wpiutil] Fix clang-tidy warnings (#5406)
c4dc697192 [hal] WS Simulation: Add message filtering capability (#5395)
0eccc3f247 [ntcore] Fix clang-tidy warnings (#5405)
f4dda4bac0 [hal] Add javadocs for JNI (NFC) (#5298)
1c20c69793 [cscore] Fix clang-tidy warnings (#5404)
1501607e48 [commands] Fix clang-tidy warnings (#5402)
991f4b0f62 [wpimath] PIDController: Add IZone (#5315)
f5b0d1484b [wpimath] Add isNear method to MathUtil (#5353)
2ce248f66c [hal] Fix clang-tidy warnings (#5401)
5fc4aee2d2 [wpimath] SwerveDriveKinematics: Rename currentChassisSpeed to desiredChassisSpeed (#5393)
50b90ceb54 [wpimath] SwerveDriveKinematics: Add reset method (#5398)
316cd2a453 [commands] Notify DriverStationSim in CommandTestBaseWithParam (#5400)
d4ea5fa902 [cscore] VideoMode: Add equals override (Java) (#5397)
d6bd72d738 [wpimath] ProfiledPIDController: Add getConstraints (#5399)
25ad5017a9 [wpimath] Refactor kinematics, odometry, and pose estimator (#5355)
5c2addda0f [doc] Add missing pneumatics docs (NFC) (#5389)
c3e04a6ea2 Fix loading tests on macos 12 (#5388)
d5ed9fb859 [wpimath] Create separate archive with just units headers (#5383)
901ab693d4 [wpimath] Use UtilityClassTest for more utility classes (#5384)
9d53231b01 [wpilib] DataLogManager: Add warning for low storage space (#5364)
d466933963 [wpiutil] Group doxygen into MPack module (#5380)
652d1c44e3 [wpiutil] Upgrade to macOS 12 to remove concept shims (#5379)
6414be0e5d [wpimath] Group units doxygen modules (#5382)
7ab5800487 [wpiutil] Fix docs typo in SmallVector (#5381)
59905ea721 Replace WPI_DEPRECATED() macro with [[deprecated]] attribute (#5373)
753cb49a5e [ntcore] Fix doxygen module in generated C types (NFC) (#5374)
1c00a52b67 [hal] Expose CAN timestamp base clock (#5357)
91cbcea841 Replace SFINAE with concepts (#5361)
d57d1a4598 [wpimath] Remove unnecessary template argument from unit formatter (#5367)
5acc5e22aa [wpimath] Only compute eigenvalues with EigenSolvers (#5369)
d3c9316a97 extend shuffleboard test timeout (#5377)
1ea868081a [ci] Fix /format command (#5376)
5fac18ff4a Update formatting to clang-format 16 (#5370)
a94a998002 [wpimath] Generalize Eigen formatter (#5360)
125f6ea101 [wpimath] Make SwerveDriveKinematics::ToChassisSpeeds() take const-ref argument (#5363)
51066a5a8a [wpimath] Move unit formatters into units library (#5358)
282c032b60 [wpilibc] Add unit-aware Joystick.GetDirection() (#5319)
073d19cb69 [build] Fix CMake warning (#5359)
01490fc77b [wpiutil] DataLog: Add documentation for append methods (NFC) (#5348)
c9b612c986 [wpilibcExamples] Make C++ state-space elevator KF and LQR match Java (#5346)
eed1e6e3cb [wpimath] Replace DiscretizeAQTaylor() with DiscretizeAQ() (#5344)
c976f40364 [readme] Document how to run examples in simulation (#5340)
4d28bdc19e [ci] Update Github Pages deploy action parameters (#5343)
e0f851871f [ci] Fix github pages deploy version (#5342)
063c8cbedc Run wpiformat (NFC) (#5341)
96e41c0447 [ci] Update deploy and sshagent actions (#5338)
fd294bdd71 [build] Fix compilation with GCC 13 (#5322)
d223e4040b [dlt] Add delete without download functionality (#5329)
abc19bcb43 [upstream_utils] Zero out commit hashes and show 40 digits in index hashes (#5336)
e909f2e687 [build] Update gradle cache repo name (#5334)
52bd5b972d [wpimath] Rewrite DARE solver (#5328)
3876a2523a [wpimath] Remove unused MatrixImpl() function (#5330)
c82fcb1975 [wpiutil] Add reflection based cleanup helper (#4919)
15ba95df7e [wpiutil] Use std::filesystem (#4941)
77c2124fc5 [wpimath] Remove Eigen's custom STL types (#4945)
27fb47ab10 [glass] Field2D: Embed standard field images (#5159)
102e4f2566 [wpilib] Remove deprecated and broken SPI methods (#5249)
463a90f1df [wpilib, hal] Add function to read the RSL state (#5312)
7a90475eec [wpilib] Update RobotBase documentation (NFC) (#5320)
218cfea16b [wpilib] DutyCycleEncoder: Fix reset behavior (#5287)
91392823ff [build] Update to gradle 8.1 (#5303)
258b7cc48b [wpilibj] Filesystem.getDeployDirectory(): Strip JNI path from user.dir (#5317)
26cc43bee1 [wpilib] Add documentation to SPI mode enum (NFC) (#5324)
ac4da9b1cb [hal] Add HAL docs for Addressable LED (NFC) (#5304)
21d4244cf7 [wpimath] Fix DCMotor docs (NFC) (#5309)
1dff81bea7 [hal] Miscellaneous HAL doc fixes (NFC) (#5306)
7ce75574bf [wpimath] Upgrade to Drake v1.15.0 (#5310)
576bd646ae [hal] Add CANManufacturer for Redux Robotics (#5305)
ee3b4621e5 [commands] Add onlyWhile and onlyIf (#5291)
40ca094686 [commands] Fix RepeatCommand calling end() twice (#5261)
9cbeb841f5 [rtns] Match imaging tool capitalization (#5265)
a63d06ff77 [examples] Add constants to java gearsbot example (#5248)
b6c43322a3 [wpilibc] XboxController: Add return tag to docs (NFC) (#5246)
5162d0001c [hal] Fix and document addressable LED timings (#5272)
90fabe9651 [wpilibj] Use method references in drive class initSendable() (#5251)
24828afd11 [wpimath] Fix desaturateWheelSpeeds to account for negative speeds (#5269)
e099948a77 [wpimath] Clean up rank notation in docs (NFC) (#5274)
fd2d8cb9c1 [hal] Use std::log2() for base-2 logarithm (#5278)
ba8c64bcff [wpimath] Fix misspelled Javadoc parameters in pose estimators (NFC) (#5292)
f53c6813d5 [wpimath] Patch Eigen warnings (#5290)
663703d370 [gitattributes] Mark json files as lf text files (#5256)
aa34aacf6e [wpilib] Shuffleboard: Keep duplicates on SelectTab() (#5198)
63512bbbb8 [wpimath] Fix potential divide-by-zero in RKDP (#5242)
9227b2166e [wpilibj] DriverStation: Fix joystick data logs (#5240)
fbf92e9190 [wpinet] ParallelTcpConnector: don't connect to duplicate addresses (#5169)
2108a61362 [ntcore] NT4 client: close timed-out connections (#5175)
0a66479693 [ntcore] Optimize scan of outgoing messages (#5227)
b510c17ef6 [hal] Fix RobotController.getComments() mishandling quotes inside the comments string (#5197)
e7a7eb2e93 [commands] WaitCommand: Remove subclass doc note (NFC) (#5200)
a465f2d8f0 [examples] Shuffleboard: Correct parameter order (#5204)
a3364422fa LICENSE.md: Bump year to 2023 (#5195)
df3242a40a [wpimath] Fix NaN in C++ MakeCostMatrix() that takes an array (#5194)
00abb8c1e0 [commands] RamseteCommand: default-initialize m_prevSpeeds (#5188)
c886273fd7 [wpilibj] DutyCycleEncoder.setDistancePerRotation(): fix simulation (#5147)
53b5fd2ace [ntcore] Use int64 for datalog type string (#5186)
56b758320f [wpilib] DataLogManager: increase time for datetime to be valid (#5185)
08f298e4cd [wpimath] Fix Pose3d log returning Twist3d NaN for theta between 1E-8 and 1E-7 (#5168)
6d0c5b19db [commands] CommandScheduler.isComposed: Remove incorrect throws clause (NFC) (#5183)
0d22cf5ff7 [wpilib] Fix enableLiveWindowInTest crashing in disabled (#5173)
32ec5b3f75 [wpilib] Add isTestEnabled and minor docs cleanup (#5172)
e5c4c6b1a7 [wpimath] Fix invalid iterator access in TimeInterpolatableBuffer (#5138)
099d048d9e [wpimath] Fix Pose3d log returning Twist3d NaN for theta between 1E-9 and 1E-8 (#5143)
4af84a1c12 Fix Typos (NFC) (#5137)
ce3686b80d [wpimath] Check LTV controller max velocity precondition (#5142)
4b0eecaee0 [commands] Subsystem: Add default command removal method (#5064)
edf4ded412 [wpilib] PH: Revert to 5V rail being fixed 5V (#5122)
4c46b6aff9 [wpilibc] Fix DataLogManager crash on exit in sim (#5125)
490ca4a68a [wpilibc] Fix XboxController::GetBackButton doc (NFC) (#5131)
cbb5b0b802 [hal] Simulation: Fix REV PH solenoids 8+ (#5132)
bb7053d9ee [hal] Fix HAL_GetRuntimeType being slow on the roboRIO (#5130)
9efed9a533 Update .clang-format to c++20 (#5121)
dbbfe1aed2 [wpilib] Use PH voltage to calc Analog pressure switch threshold (#5115)
de65a135c3 [wpilib] DutyCycleEncoderSim: Add channel number constructor (#5118)
3e9788cdff [docs] Strip path from generated NT docs (#5119)
ecb072724d [ntcore] Client::Disconnect(): actually close connection (#5113)
0d462a4561 [glass] NT view: Change string/string array to quoted (#5111)
ba37986561 [ntcore] NetworkClient::Disconnect: Add null check (#5112)
25ab9cda92 [glass,ov] Provide menu item to create topic from root (#5110)
2f6251d4a6 [glass] Set default value when publishing new topic (#5109)
e9a7bed988 [wpimath] Add timestamp getter to MathShared (#5091)
9cc14bbb43 [ntcore] Add stress test to dev executable (#5107)
8068369542 [wpinet] uv: Stop creating handles when closing loop (#5102)
805c837a42 [ntcore] Fix use-after-free in server (#5101)
fd18577ba0 [commands] Improve documentation of addRequirements (NFC) (#5103)
74dea9f05e [wpimath] Fix exception for empty pose buffer in pose estimators (#5106)
9eef79d638 [wpilib] PneumaticHub: Document range of enableCompressorAnalog (NFC) (#5099)
843574a810 [ntcore] Use wpi::Now instead of loop time for transmit time
226ef35212 [wpinet] WebSocket: Reduce server send frame overhead
b30664d630 [ntcore] Reduce initial connection overhead
804e5ce236 [examples] MecanumDrive: Fix axis comment in C++ example (NFC) (#5096)
49af88f2bb [examples] ArmSimulation: Fix flaky test (#5093)
d56314f866 [wpiutil] Disable mock time on the Rio (#5092)
43975ac7cc [examples] ArmSimulation, ElevatorSimulation: Extract mechanism to class (#5052)
5483464158 [examples, templates] Improve descriptions (NFC) (#5051)
785e7dd85c [wpilibc] SendableChooser: static_assert copy- and default-constructibility (#5078)
e57ded8c39 [ntcore] Improve disconnect error reporting (#5085)
01f0394419 [wpinet] Revert WebSocket: When Close() is called, call closed immediately (#5084)
59be120982 [wpimath] Fix Pose3d exp()/log() and add rotation vector constructor to Rotation3d (#5072)
37f065032f [wpilib] Refactor TimedRobot tests (#5068)
22a170bee7 [wpilib] Add Notifier test (#5070)
2f310a748c [wpimath] Fix DCMotor.getSpeed() (#5061)
b43ec87f57 [wpilib] ElevatorSim: Fix WouldHitLimit methods (#5057)
19267bef0c [ntcore] Output warning on property set on unpublished topic (#5059)
84cbd48d84 [ntcore] Handle excludeSelf on SetDefault (#5058)
1f35750865 [cameraserver] Add GetInstance() to all functions (#5054)
8230fc631d [wpilib] Revert throw on nonexistent SimDevice name in SimDeviceSim (#5053)
b879a6f8c6 [wpinet] WebSocket: When Close() is called, call closed immediately (#5047)
49459d3e45 [ntcore] Change wire timeout to fixed 1 second (#5048)
4079eabe9b [wpimath] Discard stale pose estimates (#5045)
fe5d226a19 [glass] Fix option for debug-level NT logging (#5049)
b7535252c2 [ntcore] Don't leak buffers in rare WS shutdown case (#5046)
b61ac6db33 [ntcore] Add client disconnect function (#5022)
7b828ce84f [wpimath] Add nearest to Pose2d and Translation2d (#4882)
08a536291b [examples] Improvements to Elevator Simulation Example (#4937)
193a10d020 [wpigui] Limit frame rate to 120 fps by default (#5030)
7867bbde0e [wpilib] Clarify DS functions provided by FMS (NFC) (#5043)
fa7c01b598 [glass] Add option for debug-level NT logging (#5007)
2b81610248 [wpiutil] Add msgpack to datalog Python example (#5032)
a4a369b8da CONTRIBUTING.md: Add unicodeit CLI to math docs guidelines (#5031)
d991f6e435 [wpilib] Throw on nonexistent SimDevice name in SimDeviceSim constructor (#5041)
a27a047ae8 [hal] Check for null in getSimDeviceName JNI (#5038)
2f96cae31a [examples] Hatchbots: Add telemetry (#5011)
83ef8f9658 [simulation] GUI: Fix buffer overflow in joystick axes copy (#5036)
4054893669 [commands] Fix C++ Select() factory (#5024)
f75acd11ce [commands] Use Timer.restart() (#5023)
8bf67b1b33 [wpimath] PIDController::Calculate(double, double): update setpoint flag (#5021)
49bb1358d8 [wpiutil] MemoryBuffer: Fix GetMemoryBufferForStream (#5017)
9c4c07c0f9 [wpiutil] Remove NDEBUG check for debug-level logging (#5018)
1a47cc2e86 [ntcore] Use full handle when subscribing (#5013)
7cd30cffbc Ignore networktables.json (#5006)
92aecab2ef [commands] Command controllers are not subclasses (NFC) (#5000)
8785bba080 [ntcore] Special-case default timestamps (#5003)
9e5b7b8040 [ntcore] Handle topicsonly followed by value subscribe (#4991)
917906530a [wpilib] Add Timer::Restart() (#4963)
00aa66e4fd [wpimath] Remove extraneous assignments from DiscretizeAB() (#4967)
893320544a [examples] C++ RamseteCommand: Fix units (#4954)
b95d0e060d [wpilib] XboxController: Fix docs discrepancy (NFC) (#4993)
008232b43c [ntcore] Write empty persistent file if none found (#4996)
522be348f4 [examples] Rewrite tags (NFC) (#4961)
d48a83dee2 [wpimath] Update Wikipedia links for quaternion to Euler angle conversion (NFC) (#4995)
504fa22143 [wpimath] Workaround intellisense Eigen issue (#4992)
b2b25bf09f [commands] Fix docs inconsistency for toggleOnFalse(Command) (NFC) (#4978)
ce3dc4eb3b [hal] Properly use control word that is in sync with DS data (#4989)
1ea48caa7d [wpilib] Fix C++ ADXRS450 and Java SPI gyro defs (#4988)
fb101925a7 [build] Include wpimathjni in commands binaries (#4981)
657951f6dd [starter] Add a process starter for use by the installer for launching tools (#4931)
a60ca9d71c [examples] Update AprilTag field load API usage (#4975)
f8a45f1558 [wpimath] Remove print statements from tests (#4977)
ecba8b99a8 [examples] Fix swapped arguments in MecanumControllerCommand example (#4976)
e95e88fdf9 [examples] Add comment to drivedistanceoffboard example (#4877)
371d15dec3 [examples] Add Computer Vision Pose Estimation and Latency Compensation Example (#4901)
cb9b8938af [sim] Enable docking in the GUI (#4960)
3b084ecbe0 [apriltag] AprilTagFieldLayout: Improve API shape for loading builtin JSONs (#4949)
27ba096ea1 [wpilib] Fix MOI calculation error in SingleJointedArmSim (#4968)
42c997a3c4 [wpimath] Fix Pose3d exponential and clean up Pose3d logarithm (#4970)
5f1a025f27 [wpilibj] Fix typo in MecanumDrive docs (NFC) (#4969)
0ebf79b54c [wpimath] Fix typo in Pose3d::Exp() docs (NFC) (#4966)
a8c465f3fb [wpimath] HolonomicDriveController: Add getters for the controllers (#4948)
a7b1ab683d [wpilibc] Add unit test for fast deconstruction of GenericHID (#4953)
bd6479dc29 [build] Add Spotless for JSON (#4956)
5cb0340a8c [hal, wpilib] Load joystick values upon code initialization (#4950)
ab0e8c37a7 [readme] Update build requirements (NFC) (#4947)
b74ac1c645 [build] Add apriltag to C++ cmake example builds (#4944)
cf1a411acf [examples] Add example programs for AprilTags detection (#4932)
1e05b21ab5 [wpimath] Fix PID atSetpoint to not return true prematurely (#4906)
e5a6197633 [wpimath] Fix SwerveDriveKinematics not initializing a new array each time (#4942)
039edcc23f [ntcore] Queue current value on subscriber creation (#4938)
f7f19207e0 [wpimath] Allow multiple vision measurements from same timestamp (#4917)
befd12911c [commands] Delete UB-causing rvalue variants of CommandPtr methods (#4923)
34519de60a [commands] Fix spacing in command composition exception (#4924)
dc4355c031 [hal] Add handle constructor and name getters for sim devices (#4925)
53d8d33bca [hal, wpilibj] Add missing distance per pulse functions to EncoderSim (#4928)
530ae40614 [apriltag] Explain what April tag poses represent (NFC) (#4930)
79f565191e [examples] DigitalCommunication, I2CCommunication: Add tests (#4865)
2cd9be413f [wpilib, examples] Cleanup PotentiometerPID, Ultrasonic, UltrasonicPID examples (#4893)
babb0c1fcf [apriltag] Add 2023 field layout JSON (#4912)
330ba45f9c [wpimath] Fix swerve kinematics util classes equals function (#4907)
51272ef6b3 [fieldImages] Add 2023 field (#4915)
0d105ab771 [commands] Deduplicate command test utils (#4897)
cf4235ea36 [wpiutil] Guard MSVC pragma in SymbolExports.h (#4911)
2d4b7b9147 [build] Update opencv version in opencv.gradle (#4909)
aec6f3d506 [ntcore] Fix client flush behavior (#4903)
bfe346c76a [build] Fix cmake java resources (#4898)

Change-Id: Ia1dd90fe42c6cd5df281b8a5b710e136f54355f4
git-subtree-dir: third_party/allwpilib
git-subtree-split: f1a82828fed8950f9a3f1586c44327027627a0c8
Signed-off-by: James Kuszmaul <jabukuszmaul+collab@gmail.com>
diff --git a/hal/src/generate/ResourceType.txt b/hal/src/generate/ResourceType.txt
index f48cb59..943d8b0 100644
--- a/hal/src/generate/ResourceType.txt
+++ b/hal/src/generate/ResourceType.txt
@@ -92,4 +92,11 @@
 kResourceType_DutyCycle = 91
 kResourceType_AddressableLEDs = 92
 kResourceType_FusionVenom = 93
-kResourceType_PS4Controller = 94
+kResourceType_CTRE_future7 = 94
+kResourceType_CTRE_future8 = 95
+kResourceType_CTRE_future9 = 96
+kResourceType_CTRE_future10 = 97
+kResourceType_CTRE_future11 = 98
+kResourceType_CTRE_future12 = 99
+kResourceType_CTRE_future13 = 100
+kResourceType_CTRE_future14 = 101
diff --git a/hal/src/main/java/edu/wpi/first/hal/AccelerometerJNI.java b/hal/src/main/java/edu/wpi/first/hal/AccelerometerJNI.java
index 3f22bcb..5f34924 100644
--- a/hal/src/main/java/edu/wpi/first/hal/AccelerometerJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/AccelerometerJNI.java
@@ -4,14 +4,59 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Accelerometer HAL JNI methods.
+ *
+ * @see "hal/Accelerometer.h"
+ */
 public class AccelerometerJNI extends JNIWrapper {
+  /**
+   * Sets the accelerometer to active or standby mode.
+   *
+   * <p>It must be in standby mode to change any configuration.
+   *
+   * @see "HAL_SetAccelerometerActive"
+   * @param active true to set to active, false for standby
+   */
   public static native void setAccelerometerActive(boolean active);
 
+  /**
+   * Sets the range of values that can be measured (either 2, 4, or 8 g-forces).
+   *
+   * <p>The accelerometer should be in standby mode when this is called.
+   *
+   * @see "HAL_SetAccelerometerRange(int range)"
+   * @param range the accelerometer range
+   */
   public static native void setAccelerometerRange(int range);
 
+  /**
+   * Gets the x-axis acceleration.
+   *
+   * <p>This is a floating point value in units of 1 g-force.
+   *
+   * @see "HAL_GetAccelerometerX()"
+   * @return the X acceleration
+   */
   public static native double getAccelerometerX();
 
+  /**
+   * Gets the y-axis acceleration.
+   *
+   * <p>This is a floating point value in units of 1 g-force.
+   *
+   * @see "HAL_GetAccelerometerY()"
+   * @return the Y acceleration
+   */
   public static native double getAccelerometerY();
 
+  /**
+   * Gets the z-axis acceleration.
+   *
+   * <p>This is a floating point value in units of 1 g-force.
+   *
+   * @see "HAL_GetAccelerometerZ()"
+   * @return the Z acceleration
+   */
   public static native double getAccelerometerZ();
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/AccumulatorResult.java b/hal/src/main/java/edu/wpi/first/hal/AccumulatorResult.java
index 441ce9f..f416ff8 100644
--- a/hal/src/main/java/edu/wpi/first/hal/AccumulatorResult.java
+++ b/hal/src/main/java/edu/wpi/first/hal/AccumulatorResult.java
@@ -9,6 +9,7 @@
 public class AccumulatorResult {
   /** The total value accumulated. */
   public long value;
+
   /** The number of sample value was accumulated over. */
   public long count;
 
diff --git a/hal/src/main/java/edu/wpi/first/hal/AddressableLEDJNI.java b/hal/src/main/java/edu/wpi/first/hal/AddressableLEDJNI.java
index 1dd80a7..b2695a3 100644
--- a/hal/src/main/java/edu/wpi/first/hal/AddressableLEDJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/AddressableLEDJNI.java
@@ -4,21 +4,97 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Addressable LED HAL JNI Methods.
+ *
+ * @see "hal/AdressableLED.h"
+ */
 public class AddressableLEDJNI extends JNIWrapper {
+  /**
+   * Initialize Addressable LED using a PWM Digital handle.
+   *
+   * @param pwmHandle handle of the digital port for PWM
+   * @return Addressable LED handle
+   * @see "HAL_InitializeAddressableLED"
+   */
   public static native int initialize(int pwmHandle);
 
+  /**
+   * Free the Addressable LED Handle.
+   *
+   * @param handle the Addressable LED handle to free
+   * @see "HAL_FreeAddressableLED"
+   */
   public static native void free(int handle);
 
+  /**
+   * Sets the length of the LED strip.
+   *
+   * <p>The max length is 5460 LEDs.
+   *
+   * @param handle the Addressable LED handle
+   * @param length the strip length
+   * @see "HAL_SetAddressableLEDLength"
+   */
   public static native void setLength(int handle, int length);
 
+  /**
+   * Sets the led output data.
+   *
+   * <p>If the output is enabled, this will start writing the next data cycle. It is safe to call,
+   * even while output is enabled.
+   *
+   * @param handle the Addressable LED handle
+   * @param data the buffer to write
+   * @see "HAL_WriteAddressableLEDData"
+   */
   public static native void setData(int handle, byte[] data);
 
+  /**
+   * Sets the bit timing.
+   *
+   * <p>By default, the driver is set up to drive WS2812Bs, so nothing needs to be set for those.
+   *
+   * @param handle the Addressable LED handle
+   * @param highTime0NanoSeconds high time for 0 bit (default 400ns)
+   * @param lowTime0NanoSeconds low time for 0 bit (default 900ns)
+   * @param highTime1NanoSeconds high time for 1 bit (default 900ns)
+   * @param lowTime1NanoSeconds low time for 1 bit (default 600ns)
+   * @see "HAL_SetAddressableLEDBitTiming"
+   */
   public static native void setBitTiming(
-      int handle, int lowTime0, int highTime0, int lowTime1, int highTime1);
+      int handle,
+      int highTime0NanoSeconds,
+      int lowTime0NanoSeconds,
+      int highTime1NanoSeconds,
+      int lowTime1NanoSeconds);
 
-  public static native void setSyncTime(int handle, int syncTime);
+  /**
+   * Sets the sync time.
+   *
+   * <p>The sync time is the time to hold output so LEDs enable. Default set for WS2812B.
+   *
+   * @param handle the Addressable LED handle
+   * @param syncTimeMicroSeconds the sync time (default 280us)
+   * @see "HAL_SetAddressableLEDSyncTime"
+   */
+  public static native void setSyncTime(int handle, int syncTimeMicroSeconds);
 
+  /**
+   * Starts the output.
+   *
+   * <p>The output writes continuously.
+   *
+   * @param handle the Addressable LED handle
+   * @see "HAL_StartAddressableLEDOutput"
+   */
   public static native void start(int handle);
 
+  /**
+   * Stops the output.
+   *
+   * @param handle the Addressable LED handle
+   * @see "HAL_StopAddressableLEDOutput"
+   */
   public static native void stop(int handle);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/AllianceStationID.java b/hal/src/main/java/edu/wpi/first/hal/AllianceStationID.java
index 7b601b3..56c2143 100644
--- a/hal/src/main/java/edu/wpi/first/hal/AllianceStationID.java
+++ b/hal/src/main/java/edu/wpi/first/hal/AllianceStationID.java
@@ -5,6 +5,7 @@
 package edu.wpi.first.hal;
 
 public enum AllianceStationID {
+  Unknown,
   Red1,
   Red2,
   Red3,
diff --git a/hal/src/main/java/edu/wpi/first/hal/AnalogGyroJNI.java b/hal/src/main/java/edu/wpi/first/hal/AnalogGyroJNI.java
index 5763f6e..cbc3d4f 100644
--- a/hal/src/main/java/edu/wpi/first/hal/AnalogGyroJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/AnalogGyroJNI.java
@@ -4,30 +4,126 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Analog Gyro JNI Functions.
+ *
+ * @see "hal/AnalogGyro.h"
+ */
 public class AnalogGyroJNI extends JNIWrapper {
+  /**
+   * Initializes an analog gyro.
+   *
+   * @param halAnalogInputHandle handle to the analog input port
+   * @return the initialized gyro handle
+   * @see "HAL_InitializeAnalogGyro"
+   */
   public static native int initializeAnalogGyro(int halAnalogInputHandle);
 
+  /**
+   * Sets up an analog gyro with the proper offsets and settings for the KOP analog gyro.
+   *
+   * @param handle the gyro handle
+   * @see "HAL_SetupAnalogGyro"
+   */
   public static native void setupAnalogGyro(int handle);
 
+  /**
+   * Frees an analog gyro.
+   *
+   * @param handle the gyro handle
+   * @see "HAL_FreeAnalogGyro"
+   */
   public static native void freeAnalogGyro(int handle);
 
+  /**
+   * Sets the analog gyro parameters to the specified values.
+   *
+   * <p>This is meant to be used if you want to reuse the values from a previous calibration.
+   *
+   * @param handle the gyro handle
+   * @param voltsPerDegreePerSecond the gyro volts scaling
+   * @param offset the gyro offset
+   * @param center the gyro center
+   * @see "HAL_SetAnalogGyroParameters"
+   */
   public static native void setAnalogGyroParameters(
       int handle, double voltsPerDegreePerSecond, double offset, int center);
 
+  /**
+   * Sets the analog gyro volts per degrees per second scaling.
+   *
+   * @param handle the gyro handle
+   * @param voltsPerDegreePerSecond the gyro volts scaling
+   * @see "HAL_SetAnalogGyroVoltsPerDegreePerSecond"
+   */
   public static native void setAnalogGyroVoltsPerDegreePerSecond(
       int handle, double voltsPerDegreePerSecond);
 
+  /**
+   * Resets the analog gyro value to 0.
+   *
+   * @param handle the gyro handle
+   * @see "HAL_ResetAnalogGyro"
+   */
   public static native void resetAnalogGyro(int handle);
 
+  /**
+   * Calibrates the analog gyro.
+   *
+   * <p>This happens by calculating the average value of the gyro over 5 seconds, and setting that
+   * as the center. Note that this call blocks for 5 seconds to perform this.
+   *
+   * @param handle the gyro handle
+   * @see "HAL_CalibrateAnalogGyro"
+   */
   public static native void calibrateAnalogGyro(int handle);
 
+  /**
+   * Sets the deadband of the analog gyro.
+   *
+   * @param handle the gyro handle
+   * @param volts the voltage deadband
+   * @see "HAL_SetAnalogGyroDeadband"
+   */
   public static native void setAnalogGyroDeadband(int handle, double volts);
 
+  /**
+   * Gets the gyro angle in degrees.
+   *
+   * @param handle the gyro handle
+   * @return the gyro angle in degrees
+   * @see "HAL_GetAnalogGyroAngle"
+   */
   public static native double getAnalogGyroAngle(int handle);
 
+  /**
+   * Gets the gyro rate in degrees/second.
+   *
+   * @param handle the gyro handle
+   * @return the gyro rate in degrees/second
+   * @see "HAL_GetAnalogGyroRate"
+   */
   public static native double getAnalogGyroRate(int handle);
 
+  /**
+   * Gets the calibrated gyro offset.
+   *
+   * <p>Can be used to not repeat a calibration but reconstruct the gyro object.
+   *
+   * @param handle the gyro handle
+   * @return the gryo offset
+   * @see "HAL_GetAnalogGyroOffset"
+   */
   public static native double getAnalogGyroOffset(int handle);
 
+  /**
+   * Gets the calibrated gyro center.
+   *
+   * <p>Can be used to not repeat a calibration but reconstruct the gyro object.
+   *
+   * @param handle the gyro handle
+   * @return the gyro center
+   * @see "HAL_GetAnalogGyroCenter"
+   */
   public static native int getAnalogGyroCenter(int handle);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/AnalogJNI.java b/hal/src/main/java/edu/wpi/first/hal/AnalogJNI.java
index b80388d..bf8b27f 100644
--- a/hal/src/main/java/edu/wpi/first/hal/AnalogJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/AnalogJNI.java
@@ -4,6 +4,14 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Analog Input / Output / Accumulator / Trigger JNI Functions.
+ *
+ * @see "hal/AnalogInput.h"
+ * @see "hal/AnalogOutput.h"
+ * @see "hal/AnalogAccumulator.h"
+ * @see "hal/AnalogTrigger.h"
+ */
 public class AnalogJNI extends JNIWrapper {
   /**
    * <i>native declaration : AthenaJava\target\native\include\HAL\Analog.h:58</i><br>
@@ -12,104 +20,481 @@
   public interface AnalogTriggerType {
     /** <i>native declaration : AthenaJava\target\native\include\HAL\Analog.h:54</i> */
     int kInWindow = 0;
+
     /** <i>native declaration : AthenaJava\target\native\include\HAL\Analog.h:55</i> */
     int kState = 1;
+
     /** <i>native declaration : AthenaJava\target\native\include\HAL\Analog.h:56</i> */
     int kRisingPulse = 2;
+
     /** <i>native declaration : AthenaJava\target\native\include\HAL\Analog.h:57</i> */
     int kFallingPulse = 3;
   }
 
+  /**
+   * Initializes the analog input port using the given port object.
+   *
+   * @param halPortHandle Handle to the port to initialize.
+   * @return the created analog input handle
+   * @see "HAL_InitializeAnalogInputPort"
+   */
   public static native int initializeAnalogInputPort(int halPortHandle);
 
+  /**
+   * Frees an analog input port.
+   *
+   * @param portHandle Handle to the analog port.
+   * @see "HAL_FreeAnalogInputPort"
+   */
   public static native void freeAnalogInputPort(int portHandle);
 
+  /**
+   * Initializes the analog output port using the given port object.
+   *
+   * @param halPortHandle handle to the port
+   * @return the created analog output handle
+   * @see "HAL_InitializeAnalogOutputPort"
+   */
   public static native int initializeAnalogOutputPort(int halPortHandle);
 
+  /**
+   * Frees an analog output port.
+   *
+   * @param portHandle the analog output handle
+   * @see "HAL_FreeAnalogOutputPort"
+   */
   public static native void freeAnalogOutputPort(int portHandle);
 
+  /**
+   * Checks that the analog module number is valid.
+   *
+   * @param module The analog module number.
+   * @return Analog module is valid and present
+   * @see "HAL_CheckAnalogModule"
+   */
   public static native boolean checkAnalogModule(byte module);
 
+  /**
+   * Checks that the analog output channel number is valid. Verifies that the analog channel number
+   * is one of the legal channel numbers. Channel numbers are 0-based.
+   *
+   * @param channel The analog output channel number.
+   * @return Analog channel is valid
+   * @see "HAL_CheckAnalogInputChannel"
+   */
   public static native boolean checkAnalogInputChannel(int channel);
 
   public static native boolean checkAnalogOutputChannel(int channel);
 
+  /**
+   * Indicates the analog input is used by a simulated device.
+   *
+   * @param handle the analog input handle
+   * @param device simulated device handle
+   * @see "HAL_SetAnalogInputSimDevice"
+   */
   public static native void setAnalogInputSimDevice(int handle, int device);
 
   public static native void setAnalogOutput(int portHandle, double voltage);
 
   public static native double getAnalogOutput(int portHandle);
 
+  /**
+   * Sets the sample rate.
+   *
+   * <p>This is a global setting for the Athena and effects all channels.
+   *
+   * @param samplesPerSecond The number of samples per channel per second.
+   * @see "HAL_SetAnalogSampleRate"
+   */
   public static native void setAnalogSampleRate(double samplesPerSecond);
 
+  /**
+   * Gets the current sample rate.
+   *
+   * <p>This assumes one entry in the scan list. This is a global setting for the Athena and effects
+   * all channels.
+   *
+   * @return Sample rate.
+   * @see "HAL_GetAnalogSampleRate"
+   */
   public static native double getAnalogSampleRate();
 
+  /**
+   * Sets the number of averaging bits.
+   *
+   * <p>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 analogPortHandle Handle to the analog port to configure.
+   * @param bits Number of bits to average.
+   * @see "HAL_SetAnalogAverageBits"
+   */
   public static native void setAnalogAverageBits(int analogPortHandle, int bits);
 
+  /**
+   * Gets the number of averaging bits.
+   *
+   * <p>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.
+   *
+   * @param analogPortHandle Handle to the analog port to use.
+   * @return Bits to average.
+   * @see "HAL_GetAnalogAverageBits"
+   */
   public static native int getAnalogAverageBits(int analogPortHandle);
 
+  /**
+   * Sets the number of oversample bits.
+   *
+   * <p>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 analogPortHandle Handle to the analog port to use.
+   * @param bits Number of bits to oversample.
+   * @see "HAL_SetAnalogOversampleBits"
+   */
   public static native void setAnalogOversampleBits(int analogPortHandle, int bits);
 
+  /**
+   * Gets the number of oversample bits.
+   *
+   * <p>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.
+   *
+   * @param analogPortHandle Handle to the analog port to use.
+   * @return Bits to oversample.
+   * @see "HAL_GetAnalogOversampleBits"
+   */
   public static native int getAnalogOversampleBits(int analogPortHandle);
 
+  /**
+   * Gets a sample straight from the channel on this module.
+   *
+   * <p>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.
+   *
+   * @param analogPortHandle Handle to the analog port to use.
+   * @return A sample straight from the channel on this module.
+   * @see "HAL_GetAnalogValue"
+   */
   public static native short getAnalogValue(int analogPortHandle);
 
+  /**
+   * Gets a sample from the output of the oversample and average engine for the channel.
+   *
+   * <p>The sample is 12-bit + the value 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.
+   *
+   * @param analogPortHandle Handle to the analog port to use.
+   * @return A sample from the oversample and average engine for the channel.
+   * @see "HAL_GetAnalogAverageValue"
+   */
   public static native int getAnalogAverageValue(int analogPortHandle);
 
+  /**
+   * Converts a voltage to a raw value for a specified channel.
+   *
+   * <p>This process depends on the calibration of each channel, so the channel must be specified.
+   *
+   * <p>todo This assumes raw values. Oversampling not supported as is.
+   *
+   * @param analogPortHandle Handle to the analog port to use.
+   * @param voltage The voltage to convert.
+   * @return The raw value for the channel.
+   * @see "HAL_GetAnalogVoltsToValue"
+   */
   public static native int getAnalogVoltsToValue(int analogPortHandle, double voltage);
 
+  /**
+   * Get the analog voltage from a raw value.
+   *
+   * @param analogPortHandle Handle to the analog port the values were read from.
+   * @param value The raw analog value
+   * @return The voltage relating to the value
+   * @see "HAL_GetAnalogValueToVolts"
+   */
   public static native double getAnalogValueToVolts(int analogPortHandle, int value);
 
+  /**
+   * Gets a scaled sample straight from the channel on this module.
+   *
+   * <p>The value is scaled to units of Volts using the calibrated scaling data from GetLSBWeight()
+   * and GetOffset().
+   *
+   * @param analogPortHandle Handle to the analog port to use.
+   * @return A scaled sample straight from the channel on this module.
+   * @see "HAL_GetAnalogVoltage"
+   */
   public static native double getAnalogVoltage(int analogPortHandle);
 
+  /**
+   * Gets a scaled sample from the output of the oversample and average engine for the channel.
+   *
+   * <p>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.
+   *
+   * @param analogPortHandle Handle to the analog port to use.
+   * @return A scaled sample from the output of the oversample and average engine for the channel.
+   * @see "HAL_GetAnalogAverageVoltage"
+   */
   public static native double getAnalogAverageVoltage(int analogPortHandle);
 
+  /**
+   * Gets the factory scaling least significant bit weight constant. The least significant bit
+   * weight constant for the channel that was calibrated in manufacturing and stored in an eeprom in
+   * the module.
+   *
+   * <p>Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
+   *
+   * @param analogPortHandle Handle to the analog port to use.
+   * @return Least significant bit weight.
+   * @see "HAL_GetAnalogLSBWeight"
+   */
   public static native int getAnalogLSBWeight(int analogPortHandle);
 
+  /**
+   * Gets the factory scaling offset constant. The offset constant for the channel that was
+   * calibrated in manufacturing and stored in an eeprom in the module.
+   *
+   * <p>Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
+   *
+   * @param analogPortHandle Handle to the analog port to use.
+   * @return Offset constant.
+   * @see "HAL_GetAnalogOffset"
+   */
   public static native int getAnalogOffset(int analogPortHandle);
 
+  /**
+   * Is the channel attached to an accumulator.
+   *
+   * @param analogPortHandle Handle to the analog port.
+   * @return The analog channel is attached to an accumulator.
+   * @see "HAL_IsAccumulatorChannel"
+   */
   public static native boolean isAccumulatorChannel(int analogPortHandle);
 
+  /**
+   * Initialize the accumulator.
+   *
+   * @param analogPortHandle Handle to the analog port.
+   * @see "HAL_InitAccumulator"
+   */
   public static native void initAccumulator(int analogPortHandle);
 
+  /**
+   * Resets the accumulator to the initial value.
+   *
+   * @param analogPortHandle Handle to the analog port.
+   * @see "HAL_ResetAccumulator"
+   */
   public static native void resetAccumulator(int analogPortHandle);
 
+  /**
+   * Set the center value of the accumulator.
+   *
+   * <p>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 make integration
+   * work and to take the device offset into account when integrating.
+   *
+   * <p>This center value is based on the output of the oversampled and averaged source from channel
+   * 1. Because of this, any non-zero oversample bits will affect the size of the value for this
+   * field.
+   *
+   * @param analogPortHandle Handle to the analog port.
+   * @param center The center value of the accumulator.
+   * @see "HAL_SetAccumulatorCenter"
+   */
   public static native void setAccumulatorCenter(int analogPortHandle, int center);
 
+  /**
+   * Set the accumulator's deadband.
+   *
+   * @param analogPortHandle Handle to the analog port.
+   * @param deadband The deadband of the accumulator.
+   * @see "HAL_SetAccumulatorDeadband"
+   */
   public static native void setAccumulatorDeadband(int analogPortHandle, int deadband);
 
+  /**
+   * Read the accumulated value.
+   *
+   * <p>Read the value that has been accumulating on channel 1. The accumulator is attached after
+   * the oversample and average engine.
+   *
+   * @param analogPortHandle Handle to the analog port.
+   * @return The 64-bit value accumulated since the last Reset().
+   * @see "HAL_GetAccumulatorValue"
+   */
   public static native long getAccumulatorValue(int analogPortHandle);
 
+  /**
+   * Read the number of accumulated values.
+   *
+   * <p>Read the count of the accumulated values since the accumulator was last Reset().
+   *
+   * @param analogPortHandle Handle to the analog port.
+   * @return The number of times samples from the channel were accumulated.
+   * @see "HAL_GetAccumulatorCount"
+   */
   public static native int getAccumulatorCount(int analogPortHandle);
 
+  /**
+   * Read the accumulated value and the number of accumulated values atomically.
+   *
+   * <p>This function reads the value and count from the FPGA atomically. This can be used for
+   * averaging.
+   *
+   * @param analogPortHandle Handle to the analog port.
+   * @param result Accumulator result.
+   * @see "HAL_GetAccumulatorOutput"
+   */
   public static native void getAccumulatorOutput(int analogPortHandle, AccumulatorResult result);
 
+  /**
+   * Initializes an analog trigger.
+   *
+   * @param analogInputHandle the analog input to use for triggering
+   * @return the created analog trigger handle
+   * @see "HAL_InitializeAnalogTrigger"
+   */
   public static native int initializeAnalogTrigger(int analogInputHandle);
 
+  /**
+   * Initializes an analog trigger with a Duty Cycle input.
+   *
+   * @param dutyCycleHandle the analog input to use for duty cycle
+   * @return tbe created analog trigger handle
+   * @see "HAL_InitializeAnalogTriggerDutyCycle"
+   */
   public static native int initializeAnalogTriggerDutyCycle(int dutyCycleHandle);
 
+  /**
+   * Frees an analog trigger.
+   *
+   * @param analogTriggerHandle the trigger handle
+   * @see "HAL_CleanAnalogTrigger"
+   */
   public static native void cleanAnalogTrigger(int analogTriggerHandle);
 
+  /**
+   * Sets the raw ADC upper and lower limits of the analog trigger.
+   *
+   * <p>HAL_SetAnalogTriggerLimitsVoltage or HAL_SetAnalogTriggerLimitsDutyCycle is likely better in
+   * most cases.
+   *
+   * @param analogTriggerHandle the trigger handle
+   * @param lower the lower ADC value
+   * @param upper the upper ADC value
+   * @see "HAL_SetAnalogTriggerLimitsRaw"
+   */
   public static native void setAnalogTriggerLimitsRaw(
       int analogTriggerHandle, int lower, int upper);
 
+  /**
+   * Sets the upper and lower limits of the analog trigger.
+   *
+   * <p>The limits are given as floating point duty cycle values.
+   *
+   * @param analogTriggerHandle the trigger handle
+   * @param lower the lower duty cycle value
+   * @param higher the upper duty cycle value
+   * @see "HAL_SetAnalogTriggerLimitsDutyCycle"
+   */
   public static native void setAnalogTriggerLimitsDutyCycle(
       int analogTriggerHandle, double lower, double higher);
 
+  /**
+   * Sets the upper and lower limits of the analog trigger.
+   *
+   * <p>The limits are given as floating point voltage values.
+   *
+   * @param analogTriggerHandle the trigger handle
+   * @param lower the lower voltage value
+   * @param upper the upper voltage value
+   * @see "HAL_SetAnalogTriggerLimitsVoltage"
+   */
   public static native void setAnalogTriggerLimitsVoltage(
       int analogTriggerHandle, double lower, double upper);
 
+  /**
+   * Configures the analog trigger to use the averaged vs. raw values.
+   *
+   * <p>If the value is true, then the averaged value is selected for the analog trigger, otherwise
+   * the immediate value is used.
+   *
+   * <p>This is not allowed to be used if filtered mode is set. This is not allowed to be used with
+   * Duty Cycle based inputs.
+   *
+   * @param analogTriggerHandle the trigger handle
+   * @param useAveragedValue true to use averaged values, false for raw
+   * @see "HAL_SetAnalogTriggerAveraged"
+   */
   public static native void setAnalogTriggerAveraged(
       int analogTriggerHandle, boolean useAveragedValue);
 
+  /**
+   * Configures the analog trigger to use a filtered value.
+   *
+   * <p>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.
+   *
+   * <p>This is not allowed to be used if averaged mode is set.
+   *
+   * @param analogTriggerHandle the trigger handle
+   * @param useFilteredValue true to use filtered values, false for average or raw
+   * @see "HAL_SetAnalogTriggerFiltered"
+   */
   public static native void setAnalogTriggerFiltered(
       int analogTriggerHandle, boolean useFilteredValue);
 
+  /**
+   * Returns the InWindow output of the analog trigger.
+   *
+   * <p>True if the analog input is between the upper and lower limits.
+   *
+   * @param analogTriggerHandle the trigger handle
+   * @return the InWindow output of the analog trigger
+   * @see "HAL_GetAnalogTriggerInWindow"
+   */
   public static native boolean getAnalogTriggerInWindow(int analogTriggerHandle);
 
+  /**
+   * Returns the TriggerState output of the analog trigger.
+   *
+   * <p>True if above upper limit. False if below lower limit. If in Hysteresis, maintain previous
+   * state.
+   *
+   * @param analogTriggerHandle the trigger handle
+   * @return the TriggerState output of the analog trigger
+   * @see "HAL_GetAnalogTriggerTriggerState"
+   */
   public static native boolean getAnalogTriggerTriggerState(int analogTriggerHandle);
 
+  /**
+   * Gets the state of the analog trigger output.
+   *
+   * @param analogTriggerHandle the trigger handle
+   * @param type the type of trigger to trigger on
+   * @return the state of the analog trigger output
+   * @see "HAL_GetAnalogTriggerOutput"
+   */
   public static native boolean getAnalogTriggerOutput(int analogTriggerHandle, int type);
 
+  /**
+   * Get the FPGA index for the AnlogTrigger.
+   *
+   * @param analogTriggerHandle the trigger handle
+   * @return the FPGA index
+   * @see "HAL_GetAnalogTriggerFPGAIndex"
+   */
   public static native int getAnalogTriggerFPGAIndex(int analogTriggerHandle);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/CANAPIJNI.java b/hal/src/main/java/edu/wpi/first/hal/CANAPIJNI.java
index 227da4d..b42def4 100644
--- a/hal/src/main/java/edu/wpi/first/hal/CANAPIJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/CANAPIJNI.java
@@ -4,31 +4,177 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * CAN API HAL JNI Functions.
+ *
+ * @see "hal/CANAPI.h"
+ */
 public class CANAPIJNI extends JNIWrapper {
+  /**
+   * Reads the current value of the millisecond-resolution timer that the CAN API functions use as a
+   * time base.
+   *
+   * @return Current value of timer used as a base time by the CAN API in milliseconds.
+   * @see "HAL_GetCANPacketBaseTime"
+   */
+  public static native long getCANPacketBaseTime();
+
+  /**
+   * Initializes a CAN device.
+   *
+   * <p>These follow the FIRST standard CAN layout.
+   * https://docs.wpilib.org/en/stable/docs/software/can-devices/can-addressing.html
+   *
+   * @param manufacturer the can manufacturer
+   * @param deviceId the device ID (0-63)
+   * @param deviceType the device type
+   * @return the created CAN handle
+   * @see "HAL_InitializeCAN"
+   */
   public static native int initializeCAN(int manufacturer, int deviceId, int deviceType);
 
+  /**
+   * Frees a CAN device.
+   *
+   * @param handle the CAN handle
+   * @see "HAL_CleanCAN"
+   */
   public static native void cleanCAN(int handle);
 
+  /**
+   * Writes a packet to the CAN device with a specific ID.
+   *
+   * <p>This ID is 10 bits.
+   *
+   * @param handle the CAN handle
+   * @param data the data to write (0-8 bytes)
+   * @param apiId the ID to write (0-1023 bits)
+   * @see "HAL_WriteCANPacket"
+   */
   public static native void writeCANPacket(int handle, byte[] data, int apiId);
 
+  /**
+   * Writes a repeating packet to the CAN device with a specific ID.
+   *
+   * <p>This ID is 10 bits.
+   *
+   * <p>The RoboRIO will automatically repeat the packet at the specified interval
+   *
+   * @param handle the CAN handle
+   * @param data the data to write (0-8 bytes)
+   * @param apiId the ID to write (0-1023)
+   * @param repeatMs the period to repeat in ms
+   * @see "HAL_WriteCANPacketRepeating"
+   */
   public static native void writeCANPacketRepeating(
       int handle, byte[] data, int apiId, int repeatMs);
 
+  /**
+   * Writes an RTR frame of the specified length to the CAN device with the specific ID.
+   *
+   * <p>By spec, the length must be equal to the length sent by the other device, otherwise behavior
+   * is unspecified.
+   *
+   * @param handle the CAN handle
+   * @param length the length of data to request (0-8)
+   * @param apiId the ID to write (0-1023)
+   * @see "HAL_WriteCANRTRFrame"
+   */
   public static native void writeCANRTRFrame(int handle, int length, int apiId);
 
+  /**
+   * Writes a packet to the CAN device with a specific ID without throwing on error.
+   *
+   * <p>This ID is 10 bits.
+   *
+   * @param handle the CAN handle
+   * @param data the data to write (0-8 bytes)
+   * @param apiId the ID to write (0-1023 bits)
+   * @return Error status variable. 0 on success.
+   * @see "HAL_WriteCANPacket"
+   */
   public static native int writeCANPacketNoThrow(int handle, byte[] data, int apiId);
 
+  /**
+   * Writes a repeating packet to the CAN device with a specific ID without throwing on error.
+   *
+   * <p>This ID is 10 bits.
+   *
+   * <p>The RoboRIO will automatically repeat the packet at the specified interval
+   *
+   * @param handle the CAN handle
+   * @param data the data to write (0-8 bytes)
+   * @param apiId the ID to write (0-1023)
+   * @param repeatMs the period to repeat in ms
+   * @return Error status variable. 0 on success.
+   * @see "HAL_WriteCANPacketRepeating"
+   */
   public static native int writeCANPacketRepeatingNoThrow(
       int handle, byte[] data, int apiId, int repeatMs);
 
+  /**
+   * Writes an RTR frame of the specified length to the CAN device with the specific ID without
+   * throwing on error.
+   *
+   * <p>By spec, the length must be equal to the length sent by the other device, otherwise behavior
+   * is unspecified.
+   *
+   * @param handle the CAN handle
+   * @param length the length of data to request (0-8)
+   * @param apiId the ID to write (0-1023)
+   * @return Error status variable. 0 on success.
+   * @see "HAL_WriteCANRTRFrame"
+   */
   public static native int writeCANRTRFrameNoThrow(int handle, int length, int apiId);
 
+  /**
+   * Stops a repeating packet with a specific ID.
+   *
+   * <p>This ID is 10 bits.
+   *
+   * @param handle the CAN handle
+   * @param apiId the ID to stop repeating (0-1023)
+   * @see "HAL_StopCANPacketRepeating"
+   */
   public static native void stopCANPacketRepeating(int handle, int apiId);
 
+  /**
+   * Reads a new CAN packet.
+   *
+   * <p>This will only return properly once per packet received. Multiple calls without receiving
+   * another packet will return false.
+   *
+   * @param handle the CAN handle
+   * @param apiId the ID to read (0-1023)
+   * @param data the packet data (8 bytes)
+   * @return true on success, false on error
+   * @see "HAL_ReadCANPacketNew"
+   */
   public static native boolean readCANPacketNew(int handle, int apiId, CANData data);
 
+  /**
+   * Reads a CAN packet. The will continuously return the last packet received, without accounting
+   * for packet age.
+   *
+   * @param handle the CAN handle
+   * @param apiId the ID to read (0-1023)
+   * @param data the packet data (8 bytes)
+   * @return true on success, false on error
+   * @see "HAL_ReadCANPacketLatest"
+   */
   public static native boolean readCANPacketLatest(int handle, int apiId, CANData data);
 
+  /**
+   * Reads 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 handle the CAN handle
+   * @param apiId the ID to read (0-1023)
+   * @param timeoutMs the timeout time for the packet
+   * @param data the packet data (8 bytes)
+   * @return true on success, false on error
+   * @see "HAL_ReadCANPacketTimeout"
+   */
   public static native boolean readCANPacketTimeout(
       int handle, int apiId, int timeoutMs, CANData data);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/CANData.java b/hal/src/main/java/edu/wpi/first/hal/CANData.java
index 0a644f6..0e29568 100644
--- a/hal/src/main/java/edu/wpi/first/hal/CANData.java
+++ b/hal/src/main/java/edu/wpi/first/hal/CANData.java
@@ -6,16 +6,21 @@
 
 @SuppressWarnings("MemberName")
 public class CANData {
+  /** Contents of the CAN frame. */
   public final byte[] data = new byte[8];
+
+  /** Length of the frame in bytes. */
   public int length;
+
+  /** CAN frame timestamp in milliseconds. */
   public long timestamp;
 
   /**
    * API used from JNI to set the data.
    *
    * @param length Length of packet in bytes.
-   * @param timestamp CAN frame timestamp in microseconds.
-   * @return Buffer containing CAN frame.
+   * @param timestamp CAN frame timestamp in milliseconds.
+   * @return Buffer to place CAN frame data in.
    */
   @SuppressWarnings("PMD.MethodReturnsInternalArray")
   public byte[] setData(int length, long timestamp) {
diff --git a/hal/src/main/java/edu/wpi/first/hal/CTREPCMJNI.java b/hal/src/main/java/edu/wpi/first/hal/CTREPCMJNI.java
index e94b183..b657da5 100644
--- a/hal/src/main/java/edu/wpi/first/hal/CTREPCMJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/CTREPCMJNI.java
@@ -4,48 +4,221 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * CTRE Pneumatic Control Module (PCM) Functions.
+ *
+ * @see "CTREPCM.h"
+ */
 public class CTREPCMJNI extends JNIWrapper {
+  /**
+   * Initializes a PCM.
+   *
+   * @param module the CAN ID to initialize
+   * @return the created PH handle
+   * @see "HAL_InitializeCTREPCM"
+   */
   public static native int initialize(int module);
 
+  /**
+   * Frees a PCM handle.
+   *
+   * @param handle the PCMhandle
+   * @see "HAL_FreeCTREPCM"
+   */
   public static native void free(int handle);
 
+  /**
+   * Checks if a solenoid channel number is valid.
+   *
+   * @param channel the channel to check
+   * @return true if the channel is valid, otherwise false
+   */
   public static native boolean checkSolenoidChannel(int channel);
 
+  /**
+   * Get whether compressor is turned on.
+   *
+   * @param handle the PCM handle
+   * @return true if the compressor is turned on
+   * @see "HAL_GetCTREPCMCompressor"
+   */
   public static native boolean getCompressor(int handle);
 
+  /**
+   * Enables the compressor closed loop control using the digital pressure switch. The compressor
+   * will turn on when the pressure switch indicates that the system is not full, and will turn off
+   * when the pressure switch indicates that the system is full.
+   *
+   * @param handle the PCM handle
+   * @param enabled true to enable closed loop control
+   * @see "HAL_SetCTREPCMClosedLoopControl"
+   */
   public static native void setClosedLoopControl(int handle, boolean enabled);
 
+  /**
+   * Get whether the PCM closed loop control is enabled.
+   *
+   * @param handle the PCM handle
+   * @return True if closed loop control is enabled, otherwise false.
+   */
   public static native boolean getClosedLoopControl(int handle);
 
+  /**
+   * Returns the state of the pressure switch.
+   *
+   * @param handle the PCM handle
+   * @return True if pressure switch indicates that the system is full, otherwise false.
+   * @see "HAL_GetCTREPCMPressureSwitch"
+   */
   public static native boolean getPressureSwitch(int handle);
 
+  /**
+   * Returns the current drawn by the compressor.
+   *
+   * @param handle the PCM handle
+   * @return The current drawn by the compressor in amps.
+   * @see "HAL_GetCTREPCMCompressorCurrent"
+   */
   public static native double getCompressorCurrent(int handle);
 
+  /**
+   * Return whether the compressor current is currently too high.
+   *
+   * @param handle the PCM handle
+   * @return True if the compressor current is too high, otherwise false.
+   * @see getCompressorCurrentTooHighStickyFault
+   * @see "HAL_GetCTREPCMCompressorCurrentTooHighFault"
+   */
   public static native boolean getCompressorCurrentTooHighFault(int handle);
 
+  /**
+   * Returns whether the compressor current has been too high since sticky faults were last cleared.
+   * This fault is persistent and can be cleared by clearAllStickyFaults()
+   *
+   * @param handle the PCM handle
+   * @return True if the compressor current has been too high since sticky faults were last cleared.
+   * @see getCompressorCurrentTooHighFault
+   * @see "HAL_GetCTREPCMCompressorCurrentTooHighStickyFault("
+   */
   public static native boolean getCompressorCurrentTooHighStickyFault(int handle);
 
+  /**
+   * Returns whether the compressor is currently shorted.
+   *
+   * @param handle the PCM handle
+   * @return True if the compressor is currently shorted, otherwise false.
+   * @see getCompressorCurrentTooHighStickyFault
+   * @see "HAL_GetCTREPCMCompressorShortedStickyFault"
+   */
   public static native boolean getCompressorShortedFault(int handle);
 
+  /**
+   * Returns whether the compressor has been shorted since sticky faults were last cleared. This
+   * fault is persistent and can be cleared by clearAllStickyFaults()
+   *
+   * @param handle the PCM handle
+   * @return True if the compressor has been shorted since sticky faults were last cleared,
+   *     otherwise false.
+   * @see getCompressorShortedFault
+   * @see "HAL_GetCTREPCMCompressorShortedFault"
+   */
   public static native boolean getCompressorShortedStickyFault(int handle);
 
+  /**
+   * Returns whether the compressor is currently disconnected.
+   *
+   * @param handle the PCM handle
+   * @return True if compressor is currently disconnected, otherwise false.
+   * @see getCompressorShortedStickyFault
+   * @see "HAL_GetCTREPCMCompressorNotConnectedFault"
+   */
   public static native boolean getCompressorNotConnectedFault(int handle);
 
+  /**
+   * Returns whether the compressor has been disconnected since sticky faults were last cleared.
+   * This fault is persistent and can be cleared by clearAllStickyFaults()
+   *
+   * @param handle the PCM handle
+   * @return True if the compressor has been disconnected since sticky faults were last cleared,
+   *     otherwise false.
+   * @see getCompressorNotConnectedFault
+   * @see "HAL_GetCTREPCMCompressorNotConnectedStickyFault"
+   */
   public static native boolean getCompressorNotConnectedStickyFault(int handle);
 
+  /**
+   * Gets a bitmask of solenoid values.
+   *
+   * @param handle the PCM handle
+   * @return solenoid values
+   * @see "HAL_GetCTREPCMSolenoids"
+   */
   public static native int getSolenoids(int handle);
 
+  /**
+   * Sets solenoids on a pneumatics module.
+   *
+   * @param handle the PCM handle
+   * @param mask bitmask to set
+   * @param values solenoid values
+   * @see "HAL_SetCTREPCMSolenoids"
+   */
   public static native void setSolenoids(int handle, int mask, int values);
 
+  /**
+   * Get a bitmask of disabled solenoids.
+   *
+   * @param handle the PCM handle
+   * @return bitmask of disabled solenoids
+   * @see "HAL_GetCTREPCMSolenoidDisabledList"
+   */
   public static native int getSolenoidDisabledList(int handle);
 
+  /**
+   * Returns whether the solenoid is currently reporting a voltage fault.
+   *
+   * @param handle the PCM handle
+   * @return True if solenoid is reporting a fault, otherwise false.
+   * @see getSolenoidVoltageStickyFault
+   * @see "HAL_GetCTREPCMSolenoidVoltageFault"
+   */
   public static native boolean getSolenoidVoltageFault(int handle);
 
+  /**
+   * Returns whether the solenoid has reported a voltage fault since sticky faults were last
+   * cleared. This fault is persistent and can be cleared by clearAllStickyFaults()
+   *
+   * @param handle the PCM handle
+   * @return True if solenoid is reporting a fault, otherwise false.
+   * @see getSolenoidVoltageFault
+   * @see "HAL_GetCTREPCMSolenoidVoltageStickyFault"
+   */
   public static native boolean getSolenoidVoltageStickyFault(int handle);
 
+  /**
+   * Clears all sticky faults on this device.
+   *
+   * @param handle the PCM handle
+   * @see "HAL_ClearAllCTREPCMStickyFaults"
+   */
   public static native void clearAllStickyFaults(int handle);
 
+  /**
+   * Fire a single solenoid shot.
+   *
+   * @param handle the PCM handle
+   * @param index solenoid index
+   * @see "HAL_FireCTREPCMOneShot"
+   */
   public static native void fireOneShot(int handle, int index);
 
+  /**
+   * Set the duration for a single solenoid shot.
+   *
+   * @param handle the PCM handle
+   * @param index solenoid index
+   * @param durMs shot duration in ms
+   * @see "HAL_SetCTREPCMOneShotDuration"
+   */
   public static native void setOneShotDuration(int handle, int index, int durMs);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/ConstantsJNI.java b/hal/src/main/java/edu/wpi/first/hal/ConstantsJNI.java
index aba5b33..4843449 100644
--- a/hal/src/main/java/edu/wpi/first/hal/ConstantsJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/ConstantsJNI.java
@@ -4,6 +4,17 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Constants HAL JNI functions.
+ *
+ * @see "hal/Constants.h"
+ */
 public class ConstantsJNI extends JNIWrapper {
+  /**
+   * Gets the number of FPGA system clock ticks per microsecond.
+   *
+   * @return the number of clock ticks per microsecond
+   * @see "HAL_GetSystemClockTicksPerMicrosecond"
+   */
   public static native int getSystemClockTicksPerMicrosecond();
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/CounterJNI.java b/hal/src/main/java/edu/wpi/first/hal/CounterJNI.java
index 8b95228..ebc4cff 100644
--- a/hal/src/main/java/edu/wpi/first/hal/CounterJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/CounterJNI.java
@@ -6,59 +6,277 @@
 
 import java.nio.IntBuffer;
 
+/**
+ * Counter HAL JNI functions.
+ *
+ * @see "hal/Counter.h"
+ */
 public class CounterJNI extends JNIWrapper {
   public static final int TWO_PULSE = 0;
   public static final int SEMI_PERIOD = 1;
   public static final int PULSE_LENGTH = 2;
   public static final int EXTERNAL_DIRECTION = 3;
 
+  /**
+   * Initializes a counter.
+   *
+   * @param mode the counter mode
+   * @param index the compressor index (output)
+   * @return the created handle
+   * @see "HAL_InitializeCounter"
+   */
   public static native int initializeCounter(int mode, IntBuffer index);
 
+  /**
+   * Frees a counter.
+   *
+   * @param counterHandle the counter handle
+   * @see "HAL_FreeCounter"
+   */
   public static native void freeCounter(int counterHandle);
 
+  /**
+   * Sets the average sample size of a counter.
+   *
+   * @param counterHandle the counter handle
+   * @param size the size of samples to average
+   * @see "HAL_SetCounterAverageSize"
+   */
   public static native void setCounterAverageSize(int counterHandle, int size);
 
+  /**
+   * Sets the source object that causes the counter to count up.
+   *
+   * @param counterHandle the counter handle
+   * @param digitalSourceHandle the digital source handle (either a HAL_AnalogTriggerHandle or a
+   *     HAL_DigitalHandle)
+   * @param analogTriggerType the analog trigger type if the source is an analog trigger
+   * @see "HAL_SetCounterUpSource"
+   */
   public static native void setCounterUpSource(
       int counterHandle, int digitalSourceHandle, int analogTriggerType);
 
+  /**
+   * Sets the up source to either detect rising edges or falling edges.
+   *
+   * <p>Note that both are allowed to be set true at the same time without issues.
+   *
+   * @param counterHandle the counter handle
+   * @param risingEdge true to trigger on rising
+   * @param fallingEdge true to trigger on falling
+   * @see "HAL_SetCounterUpSourceEdge"
+   */
   public static native void setCounterUpSourceEdge(
       int counterHandle, boolean risingEdge, boolean fallingEdge);
 
+  /**
+   * Disables the up counting source to the counter.
+   *
+   * @param counterHandle the counter handle
+   * @see "HAL_ClearCounterUpSource"
+   */
   public static native void clearCounterUpSource(int counterHandle);
 
+  /**
+   * Sets the source object that causes the counter to count down.
+   *
+   * @param counterHandle the counter handle
+   * @param digitalSourceHandle the digital source handle (either a HAL_AnalogTriggerHandle or a
+   *     HAL_DigitalHandle)
+   * @param analogTriggerType the analog trigger type if the source is an analog trigger
+   * @see "HAL_SetCounterDownSource"
+   */
   public static native void setCounterDownSource(
       int counterHandle, int digitalSourceHandle, int analogTriggerType);
 
+  /**
+   * Sets the down source to either detect rising edges or falling edges. Note that both are allowed
+   * to be set true at the same time without issues.
+   *
+   * @param counterHandle the counter handle
+   * @param risingEdge true to trigger on rising
+   * @param fallingEdge true to trigger on falling
+   * @see "HAL_SetCounterDownSourceEdge"
+   */
   public static native void setCounterDownSourceEdge(
       int counterHandle, boolean risingEdge, boolean fallingEdge);
 
+  /**
+   * Disables the down counting source to the counter.
+   *
+   * @param counterHandle the counter handle
+   * @see "HAL_ClearCounterDownSource"
+   */
   public static native void clearCounterDownSource(int counterHandle);
 
+  /**
+   * Sets standard up / down counting mode on this counter.
+   *
+   * <p>Up and down counts are sourced independently from two inputs.
+   *
+   * @param counterHandle the counter handle
+   * @see "HAL_SetCounterUpDownMode"
+   */
   public static native void setCounterUpDownMode(int counterHandle);
 
+  /**
+   * Sets directional counting mode on this counter.
+   *
+   * <p>The direction is determined by the B input, with counting happening with the A input.
+   *
+   * @param counterHandle the counter handle
+   * @see "HAL_SetCounterExternalDirectionMode"
+   */
   public static native void setCounterExternalDirectionMode(int counterHandle);
 
+  /**
+   * Sets Semi-period mode on this counter.
+   *
+   * <p>The counter counts up based on the time the input is triggered. High or Low depends on the
+   * highSemiPeriod parameter.
+   *
+   * @param counterHandle the counter handle
+   * @param highSemiPeriod true for counting when the input is high, false for low
+   * @see "HAL_SetCounterSemiPeriodMode"
+   */
   public static native void setCounterSemiPeriodMode(int counterHandle, boolean highSemiPeriod);
 
+  /**
+   * Configures the counter to count in up or down based on the length of the input pulse.
+   *
+   * <p>This mode is most useful for direction sensitive gear tooth sensors.
+   *
+   * @param counterHandle the counter handle
+   * @param threshold The pulse length beyond which the counter counts the opposite direction
+   *     (seconds)
+   * @see "HAL_SetCounterPulseLengthMode"
+   */
   public static native void setCounterPulseLengthMode(int counterHandle, double threshold);
 
+  /**
+   * Gets 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 counterHandle the counter handle
+   * @return SamplesToAverage The number of samples being averaged (from 1 to 127)
+   * @see "HAL_GetCounterSamplesToAverage"
+   */
   public static native int getCounterSamplesToAverage(int counterHandle);
 
+  /**
+   * Sets 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 counterHandle the counter handle
+   * @param samplesToAverage The number of samples to average from 1 to 127
+   * @see "HAL_SetCounterSamplesToAverage"
+   */
   public static native void setCounterSamplesToAverage(int counterHandle, int samplesToAverage);
 
+  /**
+   * Resets the Counter to zero.
+   *
+   * <p>Sets the counter value to zero. This does not effect the running state of the counter, just
+   * sets the current value to zero.
+   *
+   * @param counterHandle the counter handle
+   * @see "HAL_ResetCounter"
+   */
   public static native void resetCounter(int counterHandle);
 
+  /**
+   * Reads the current counter value.
+   *
+   * <p>Reads 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.
+   *
+   * @param counterHandle the counter handle
+   * @return the current counter value
+   * @see "HAL_GetCounter"
+   */
   public static native int getCounter(int counterHandle);
 
+  /**
+   * Gets the Period of the most recent count.
+   *
+   * <p>Returns the time interval of the most recent count. This can be used for velocity
+   * calculations to determine shaft speed.
+   *
+   * @param counterHandle the counter handle
+   * @return the period of the last two pulses in units of seconds
+   * @see "HAL_GetCounterPeriod"
+   */
   public static native double getCounterPeriod(int counterHandle);
 
+  /**
+   * Sets the maximum period where the device is still considered "moving".
+   *
+   * <p>Sets the maximum period where the device is considered moving. This value is used to
+   * determine the "stopped" state of the counter using the HAL_GetCounterStopped method.
+   *
+   * @param counterHandle the counter handle
+   * @param maxPeriod the maximum period where the counted device is considered moving in seconds
+   * @see "HAL_SetCounterMaxPeriod"
+   */
   public static native void setCounterMaxPeriod(int counterHandle, double maxPeriod);
 
+  /**
+   * Selects whether you want to continue updating the event timer output when there are no samples
+   * captured.
+   *
+   * <p>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.
+   *
+   * <p>If you enable the update when empty, you will be notified of the stopped source and the
+   * event time will report 0 samples.
+   *
+   * <p>If you disable update when empty, the most recent average will remain on the output until a
+   * new sample is acquired.
+   *
+   * <p>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 counterHandle the counter handle
+   * @param enabled true to enable counter updating with no samples
+   * @see "HAL_SetCounterUpdateWhenEmpty"
+   */
   public static native void setCounterUpdateWhenEmpty(int counterHandle, boolean enabled);
 
+  /**
+   * Determines if the clock is stopped.
+   *
+   * <p>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.
+   *
+   * @param counterHandle the counter handle
+   * @return true if the most recent counter period exceeds the MaxPeriod value set by SetMaxPeriod
+   * @see "HAL_GetCounterStopped"
+   */
   public static native boolean getCounterStopped(int counterHandle);
 
+  /**
+   * Gets the last direction the counter value changed.
+   *
+   * @param counterHandle the counter handle
+   * @return the last direction the counter value changed
+   * @see "HAL_GetCounterDirection"
+   */
   public static native boolean getCounterDirection(int counterHandle);
 
+  /**
+   * Sets the Counter to return reversed sensing on the direction.
+   *
+   * <p>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 counterHandle the counter handle
+   * @param reverseDirection true if the value counted should be negated.
+   * @see "HAL_SetCounterReverseDirection"
+   */
   public static native void setCounterReverseDirection(int counterHandle, boolean reverseDirection);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/DIOJNI.java b/hal/src/main/java/edu/wpi/first/hal/DIOJNI.java
index 689a95e..3330f4a 100644
--- a/hal/src/main/java/edu/wpi/first/hal/DIOJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/DIOJNI.java
@@ -4,42 +4,178 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Digital Input/Output (IO) JNI Functions.
+ *
+ * @see "hal/DIO.h"
+ */
 public class DIOJNI extends JNIWrapper {
+  /**
+   * Creates a new instance of a digital port.
+   *
+   * @param halPortHandle the port handle to create from
+   * @param input true for input, false for output
+   * @return the created digital handle
+   * @see "HAL_InitializeDIOPort"
+   */
   public static native int initializeDIOPort(int halPortHandle, boolean input);
 
+  /**
+   * Checks if a DIO channel is valid.
+   *
+   * @param channel the channel number to check
+   * @return true if the channel is valid, otherwise false
+   * @see "HAL_CheckDIOChannel"
+   */
   public static native boolean checkDIOChannel(int channel);
 
+  /**
+   * Frees a DIO port.
+   *
+   * @param dioPortHandle the DIO channel handle
+   * @see "HAL_FreeDIOPort"
+   */
   public static native void freeDIOPort(int dioPortHandle);
 
+  /**
+   * Indicates the DIO channel is used by a simulated device.
+   *
+   * @param handle the DIO channel handle
+   * @param device simulated device handle
+   * @see "HAL_SetDIOSimDevice"
+   */
   public static native void setDIOSimDevice(int handle, int device);
 
+  /**
+   * Writes a digital value to a DIO channel.
+   *
+   * @param dioPortHandle the digital port handle
+   * @param value the state to set the digital channel (if it is configured as an output)
+   * @see "HAL_SetDIO"
+   */
   public static native void setDIO(int dioPortHandle, boolean value);
 
+  /**
+   * Sets the direction of a DIO channel.
+   *
+   * @param dioPortHandle the digital port handle
+   * @param input true to set input, false for output
+   * @see "HAL_SetDIODirection"
+   */
   public static native void setDIODirection(int dioPortHandle, boolean input);
 
+  /**
+   * Reads a digital value from a DIO channel.
+   *
+   * @param dioPortHandle the digital port handle
+   * @return the state of the specified channel
+   * @see "HAL_GetDIO"
+   */
   public static native boolean getDIO(int dioPortHandle);
 
+  /**
+   * Reads the direction of a DIO channel.
+   *
+   * @param dioPortHandle the digital port handle
+   * @return true for input, false for output
+   * @see "HAL_GetDIODirection"
+   */
   public static native boolean getDIODirection(int dioPortHandle);
 
+  /**
+   * Generates a single digital pulse.
+   *
+   * <p>Write a pulse to the specified digital output channel. There can only be a single pulse
+   * going at any time.
+   *
+   * @param dioPortHandle the digital port handle
+   * @param pulseLengthSeconds the active length of the pulse (in seconds)
+   * @see "HAL_Pulse"
+   */
   public static native void pulse(int dioPortHandle, double pulseLengthSeconds);
 
+  /**
+   * Generates a single digital pulse on multiple channels.
+   *
+   * <p>Write a pulse to the channels enabled by the mask. There can only be a single pulse going at
+   * any time.
+   *
+   * @param channelMask the channel mask
+   * @param pulseLengthSeconds the active length of the pulse (in seconds)
+   * @see "HAL_PulseMultiple"
+   */
   public static native void pulseMultiple(long channelMask, double pulseLengthSeconds);
 
+  /**
+   * Checks a DIO line to see if it is currently generating a pulse.
+   *
+   * @param dioPortHandle the digital port handle
+   * @return true if a pulse is in progress, otherwise false
+   * @see "HAL_IsPulsing"
+   */
   public static native boolean isPulsing(int dioPortHandle);
 
+  /**
+   * Checks if any DIO line is currently generating a pulse.
+   *
+   * @return true if a pulse on some line is in progress
+   * @see "HAL_IsAnyPulsing"
+   */
   public static native boolean isAnyPulsing();
 
   public static native short getLoopTiming();
 
+  /**
+   * Allocates a DO PWM Generator.
+   *
+   * @return the allocated digital PWM handle
+   */
   public static native int allocateDigitalPWM();
 
+  /**
+   * Frees the resource associated with a DO PWM generator.
+   *
+   * @param pwmGenerator the digital PWM handle
+   * @see "HAL_FreeDigitalPWM"
+   */
   public static native void freeDigitalPWM(int pwmGenerator);
 
+  /**
+   * Changes the frequency of the DO PWM generator.
+   *
+   * <p>The valid range is from 0.6 Hz to 19 kHz.
+   *
+   * <p>The frequency resolution is logarithmic.
+   *
+   * @param rate the frequency to output all digital output PWM signals
+   * @see "HAL_SetDigitalPWMRate"
+   */
   public static native void setDigitalPWMRate(double rate);
 
+  /**
+   * Configures the duty-cycle of the PWM generator.
+   *
+   * @param pwmGenerator the digital PWM handle
+   * @param dutyCycle the percent duty cycle to output [0..1]
+   * @see "HAL_SetDigitalPWMDutyCycle"
+   */
   public static native void setDigitalPWMDutyCycle(int pwmGenerator, double dutyCycle);
 
+  /**
+   * Configures the digital PWM to be a PPS signal with specified duty cycle.
+   *
+   * @param pwmGenerator the digital PWM handle
+   * @param dutyCycle the percent duty cycle to output [0..1]
+   * @see "HAL_SetDigitalPWMPPS"
+   */
   public static native void setDigitalPWMPPS(int pwmGenerator, double dutyCycle);
 
+  /**
+   * Configures which DO channel the PWM signal is output on.
+   *
+   * @param pwmGenerator the digital PWM handle
+   * @param channel the channel to output on
+   * @see "HAL_SetDigitalPWMOutputChannel"
+   */
   public static native void setDigitalPWMOutputChannel(int pwmGenerator, int channel);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/DMAJNI.java b/hal/src/main/java/edu/wpi/first/hal/DMAJNI.java
index 9a0cfeb..00000d2 100644
--- a/hal/src/main/java/edu/wpi/first/hal/DMAJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/DMAJNI.java
@@ -4,53 +4,245 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * DMA HAL JNI functions.
+ *
+ * @see "hal/DHA.h"
+ */
 public class DMAJNI extends JNIWrapper {
+  /**
+   * Initializes an object for performing DMA transfers.
+   *
+   * @return the created dma handle
+   * @see "HAL_InitializeDMA"
+   */
   public static native int initialize();
 
+  /**
+   * Frees a DMA object.
+   *
+   * @param handle the dma handle
+   * @see "HAL_FreeDMA"
+   */
   public static native void free(int handle);
 
+  /**
+   * Pauses or unpauses a DMA transfer.
+   *
+   * <p>This can only be called while DMA is running.
+   *
+   * @param handle the dma handle
+   * @param pause true to pause transfers, false to resume.
+   * @see "HAL_SetDMAPause"
+   */
   public static native void setPause(int handle, boolean pause);
 
+  /**
+   * Sets DMA transfers to occur at a specific timed interval.
+   *
+   * <p>This will remove any external triggers. Only timed or external is supported.
+   *
+   * <p>Only 1 timed period is supported.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @param periodSeconds the period to trigger in seconds
+   * @see "HAL_SetDMATimedTrigger"
+   */
   public static native void setTimedTrigger(int handle, double periodSeconds);
 
+  /**
+   * Sets DMA transfers to occur at a specific timed interval in FPGA cycles.
+   *
+   * <p>This will remove any external triggers. Only timed or external is supported.
+   *
+   * <p>Only 1 timed period is supported
+   *
+   * <p>The FPGA currently runs at 40 MHz, but this can change.
+   * HAL_GetSystemClockTicksPerMicrosecond can be used to get a computable value for this.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @param cycles the period to trigger in FPGA cycles
+   * @see "HAL_SetDMATimedTriggerCycles"
+   */
   public static native void setTimedTriggerCycles(int handle, int cycles);
 
+  /**
+   * Adds position data for an encoder to be collected by DMA.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @param encoderHandle the encoder to add
+   * @see "HAL_AddDMAEncoder"
+   */
   public static native void addEncoder(int handle, int encoderHandle);
 
+  /**
+   * Adds timer data for an encoder to be collected by DMA.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @param encoderHandle the encoder to add
+   * @see "HAL_AddDMAEncoderPeriod"
+   */
   public static native void addEncoderPeriod(int handle, int encoderHandle);
 
+  /**
+   * Adds position data for an counter to be collected by DMA.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @param counterHandle the counter to add
+   * @see "HAL_AddDMACounter"
+   */
   public static native void addCounter(int handle, int counterHandle);
 
+  /**
+   * Adds timer data for an counter to be collected by DMA.
+   *
+   * @param handle the dma handle
+   * @param counterHandle the counter to add
+   * @see "HAL_AddDMACounterPeriod"
+   */
   public static native void addCounterPeriod(int handle, int counterHandle);
 
+  /**
+   * Adds a digital source to be collected by DMA.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @param digitalSourceHandle the digital source to add
+   * @see "HAL_AddDMADigitalSource"
+   */
   public static native void addDigitalSource(int handle, int digitalSourceHandle);
 
+  /**
+   * Adds a duty cycle input to be collected by DMA.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @param dutyCycleHandle the duty cycle input to add
+   * @see "HAL_AddDMADutyCycle"
+   */
   public static native void addDutyCycle(int handle, int dutyCycleHandle);
 
+  /**
+   * Adds an analog input to be collected by DMA.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @param analogInputHandle the analog input to add
+   * @see "HAL_AddDMAAnalogInput"
+   */
   public static native void addAnalogInput(int handle, int analogInputHandle);
 
+  /**
+   * Adds averaged data of an analog input to be collected by DMA.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @param analogInputHandle the analog input to add
+   * @see "HAL_AddDMAAveragedAnalogInput"
+   */
   public static native void addAveragedAnalogInput(int handle, int analogInputHandle);
 
+  /**
+   * Adds accumulator data of an analog input to be collected by DMA.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @param analogInputHandle the analog input to add
+   * @see "HAL_AddDMAAnalogAccumulator"
+   */
   public static native void addAnalogAccumulator(int handle, int analogInputHandle);
 
+  /**
+   * Sets DMA transfers to occur on an external trigger.
+   *
+   * <p>This will remove any timed trigger set. Only timed or external is supported.
+   *
+   * <p>Up to 8 external triggers are currently supported.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @param digitalSourceHandle the digital source handle (either a HAL_AnalogTriggerHandle or a
+   *     HAL_DigitalHandle)
+   * @param analogTriggerType the analog trigger type if the source is an analog trigger
+   * @param rising true to trigger on rising edge
+   * @param falling true to trigger on falling edge
+   * @return the index of the trigger
+   * @see "HAL_SetDMAExternalTrigger"
+   */
   public static native int setExternalTrigger(
       int handle, int digitalSourceHandle, int analogTriggerType, boolean rising, boolean falling);
 
+  /**
+   * Clear all sensors from the DMA collection list.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @see "HAL_ClearDMASensors"
+   */
   public static native void clearSensors(int handle);
 
+  /**
+   * Clear all external triggers from the DMA trigger list.
+   *
+   * <p>This can only be called if DMA is not started.
+   *
+   * @param handle the dma handle
+   * @see "HAL_ClearDMAExternalTriggers"
+   */
   public static native void clearExternalTriggers(int handle);
 
+  /**
+   * Starts DMA Collection.
+   *
+   * @param handle the dma handle
+   * @param queueDepth the number of objects to be able to queue
+   * @see "HAL_StartDMA"
+   */
   public static native void startDMA(int handle, int queueDepth);
 
+  /**
+   * Stops DMA Collection.
+   *
+   * @param handle the dma handle
+   * @see "HAL_StopDMA"
+   */
   public static native void stopDMA(int handle);
 
-  // 0-21 channelOffsets
-  // 22: capture size
-  // 23: triggerChannels (bitflags)
-  // 24: remaining
-  // 25: read status
+  /**
+   * Reads a DMA sample from the queue.
+   *
+   * @param handle the dma handle
+   * @param timeoutSeconds the time to wait for data to be queued before timing out
+   * @param buffer the sample object to place data into
+   * @param sampleStore index 0-21 channelOffsets, index 22: capture size, index 23: triggerChannels
+   *     (bitflags), index 24: remaining, index 25: read status
+   * @return timestamp of the DMA Sample
+   */
   public static native long readDMA(
       int handle, double timeoutSeconds, int[] buffer, int[] sampleStore);
 
+  /**
+   * Get the sensor DMA sample.
+   *
+   * @param handle the dma handle
+   * @return The DMA sample
+   */
   public static native DMAJNISample.BaseStore getSensorReadData(int handle);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/DigitalGlitchFilterJNI.java b/hal/src/main/java/edu/wpi/first/hal/DigitalGlitchFilterJNI.java
index cf0a781..9a16984 100644
--- a/hal/src/main/java/edu/wpi/first/hal/DigitalGlitchFilterJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/DigitalGlitchFilterJNI.java
@@ -4,12 +4,59 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Digital Glitch Filter JNI functions.
+ *
+ * @see "hal/DIO.h"
+ */
 public class DigitalGlitchFilterJNI extends JNIWrapper {
+  /**
+   * Writes the filter index from the FPGA.
+   *
+   * <p>Set the filter index used to filter out short pulses.
+   *
+   * @param digitalPortHandle the digital port handle
+   * @param filterIndex the filter index (Must be in the range 0 - 3, where 0 means "none" and 1 - 3
+   *     means filter # filterIndex - 1)
+   * @see "HAL_SetFilterSelect"
+   */
   public static native void setFilterSelect(int digitalPortHandle, int filterIndex);
 
+  /**
+   * Reads the filter index from the FPGA.
+   *
+   * <p>Gets the filter index used to filter out short pulses.
+   *
+   * @param digitalPortHandle the digital port handle
+   * @return the filter index (Must be in the range 0 - 3, where 0 means "none" and 1 - 3 means
+   *     filter # filterIndex - 1)
+   * @see "HAL_GetFilterSelect"
+   */
   public static native int getFilterSelect(int digitalPortHandle);
 
+  /**
+   * Sets the filter period for the specified filter index.
+   *
+   * <p>Sets the filter period in FPGA cycles. Even though there are 2 different filter index
+   * domains (MXP vs HDR), ignore that distinction for now since it complicates the interface. That
+   * can be changed later.
+   *
+   * @param filterIndex the filter index, 0 - 2
+   * @param fpgaCycles the number of cycles that the signal must not transition to be counted as a
+   *     transition.
+   * @see "HAL_SetFilterPeriod"
+   */
   public static native void setFilterPeriod(int filterIndex, int fpgaCycles);
 
+  /**
+   * Gets the filter period for the specified filter index.
+   *
+   * <p>Gets the filter period in FPGA cycles. Even though there are 2 different filter index
+   * domains (MXP vs HDR), ignore that distinction for now since it complicates the interface.
+   *
+   * @param filterIndex the filter index, 0 - 2
+   * @return The number of FPGA cycles of the filter period.
+   * @see "HAL_GetFilterPeriod"
+   */
   public static native int getFilterPeriod(int filterIndex);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/DriverStationJNI.java b/hal/src/main/java/edu/wpi/first/hal/DriverStationJNI.java
index f40a38c..4a46b52 100644
--- a/hal/src/main/java/edu/wpi/first/hal/DriverStationJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/DriverStationJNI.java
@@ -6,21 +6,88 @@
 
 import java.nio.ByteBuffer;
 
+/**
+ * Driver Station JNI Functions.
+ *
+ * @see "hal/DriverStation.h"
+ * @see "hal/FRCUsageReporting.h"
+ */
 public class DriverStationJNI extends JNIWrapper {
+  /**
+   * Sets the program starting flag in the DS.
+   *
+   * <p>This is what changes the DS to showing robot code ready.
+   *
+   * @see "HAL_ObserveUserProgramStarting"
+   */
   public static native void observeUserProgramStarting();
 
+  /**
+   * Sets the disabled flag in the DS.
+   *
+   * <p>This is used for the DS to ensure the robot is properly responding to its state request.
+   * Ensure this gets called about every 50ms, or the robot will be disabled by the DS.
+   *
+   * @see "HAL_ObserveUserProgramDisabled"
+   */
   public static native void observeUserProgramDisabled();
 
+  /**
+   * Sets the autonomous enabled flag in the DS.
+   *
+   * <p>This is used for the DS to ensure the robot is properly responding to its state request.
+   * Ensure this gets called about every 50ms, or the robot will be disabled by the DS.
+   *
+   * @see "HAL_ObserveUserProgramAutonomous"
+   */
   public static native void observeUserProgramAutonomous();
 
+  /**
+   * Sets the teleoperated enabled flag in the DS.
+   *
+   * <p>This is used for the DS to ensure the robot is properly responding to its state request.
+   * Ensure this gets called about every 50ms, or the robot will be disabled by the DS.
+   *
+   * @see "HAL_ObserveUserProgramTeleop"
+   */
   public static native void observeUserProgramTeleop();
 
+  /**
+   * Sets the test mode flag in the DS.
+   *
+   * <p>This is used for the DS to ensure the robot is properly responding to its state request.
+   * Ensure this gets called about every 50ms, or the robot will be disabled by the DS.
+   *
+   * @see "HAL_ObserveUserProgramTest"
+   */
   public static native void observeUserProgramTest();
 
+  /**
+   * Report the usage of a resource of interest.
+   *
+   * <p>Original signature: <code>uint32_t report(tResourceType, uint8_t, uint8_t, const
+   * char*)</code>
+   *
+   * @param resource one of the values in the tResourceType above.
+   * @param instanceNumber an index that identifies the resource instance.
+   * @see "HAL_Report"
+   */
   public static void report(int resource, int instanceNumber) {
     report(resource, instanceNumber, 0, "");
   }
 
+  /**
+   * Report the usage of a resource of interest.
+   *
+   * <p>Original signature: <code>uint32_t report(tResourceType, uint8_t, uint8_t, const
+   * char*)</code>
+   *
+   * @param resource one of the values in the tResourceType above.
+   * @param instanceNumber an index that identifies the resource instance.
+   * @param context an optional additional context number for some cases (such as module number).
+   *     Set to 0 to omit.
+   * @see "HAL_Report"
+   */
   public static void report(int resource, int instanceNumber, int context) {
     report(resource, instanceNumber, context, "");
   }
@@ -31,19 +98,36 @@
    * <p>Original signature: <code>uint32_t report(tResourceType, uint8_t, uint8_t, const
    * char*)</code>
    *
-   * @param resource one of the values in the tResourceType above (max value 51).
+   * @param resource one of the values in the tResourceType above.
    * @param instanceNumber an index that identifies the resource instance.
    * @param context an optional additional context number for some cases (such as module number).
    *     Set to 0 to omit.
    * @param feature a string to be included describing features in use on a specific resource.
    *     Setting the same resource more than once allows you to change the feature string.
-   * @return TODO
+   * @return the index of the added value in NetComm
+   * @see "HAL_Report"
    */
   public static native int report(int resource, int instanceNumber, int context, String feature);
 
+  /**
+   * Gets the current control word of the driver station.
+   *
+   * <p>The control word contains the robot state.
+   *
+   * @return the control word
+   * @see "HAL_GetControlWord"
+   * @see getControlWord for a version easier to parse
+   */
   public static native int nativeGetControlWord();
 
-  @SuppressWarnings("MissingJavadocMethod")
+  /**
+   * Gets the current control word of the driver station.
+   *
+   * <p>The control work contains the robot state.
+   *
+   * @param controlWord the ControlWord to update
+   * @see "HAL_GetControlWord"
+   */
   public static void getControlWord(ControlWord controlWord) {
     int word = nativeGetControlWord();
     controlWord.update(
@@ -55,18 +139,32 @@
         ((word >> 5) & 1) != 0);
   }
 
+  /**
+   * Gets the current alliance station ID.
+   *
+   * @return the alliance station ID int
+   * @see "HAL_GetAllianceStation"
+   */
   private static native int nativeGetAllianceStation();
 
-  public static final int kRed1AllianceStation = 0;
-  public static final int kRed2AllianceStation = 1;
-  public static final int kRed3AllianceStation = 2;
-  public static final int kBlue1AllianceStation = 3;
-  public static final int kBlue2AllianceStation = 4;
-  public static final int kBlue3AllianceStation = 5;
+  public static final int kUnknownAllianceStation = 0;
+  public static final int kRed1AllianceStation = 1;
+  public static final int kRed2AllianceStation = 2;
+  public static final int kRed3AllianceStation = 3;
+  public static final int kBlue1AllianceStation = 4;
+  public static final int kBlue2AllianceStation = 5;
+  public static final int kBlue3AllianceStation = 6;
 
-  @SuppressWarnings("MissingJavadocMethod")
+  /**
+   * Gets the current alliance station ID.
+   *
+   * @return the alliance station ID as AllianceStationID
+   * @see "HAL_GetAllianceStation"
+   */
   public static AllianceStationID getAllianceStation() {
     switch (nativeGetAllianceStation()) {
+      case kUnknownAllianceStation:
+        return AllianceStationID.Unknown;
       case kRed1AllianceStation:
         return AllianceStationID.Red1;
       case kRed2AllianceStation:
@@ -88,32 +186,156 @@
   public static final int kMaxJoystickPOVs = 12;
   public static final int kMaxJoysticks = 6;
 
+  /**
+   * Gets the axes of a specific joystick.
+   *
+   * @param joystickNum the joystick number
+   * @param axesArray the axes values
+   * @return number of joystick axes, or 0 for error
+   * @see "HAL_GetJoystickAxes"
+   */
   public static native int getJoystickAxes(byte joystickNum, float[] axesArray);
 
+  /**
+   * Gets the axes of a specific joystick.
+   *
+   * @param joystickNum the joystick number
+   * @param rawAxesArray the raw int axes values (0-255)
+   * @return number of joystick axes, or 0 for error
+   * @see "HAL_GetJoystickAxes"
+   */
   public static native int getJoystickAxesRaw(byte joystickNum, int[] rawAxesArray);
 
+  /**
+   * Gets the POVs of a specific joystick.
+   *
+   * @param joystickNum the joystick number
+   * @param povsArray the POV values
+   * @return number of POVs, or 0 for error
+   * @see "HAL_GetJoystickPOVs"
+   */
   public static native int getJoystickPOVs(byte joystickNum, short[] povsArray);
 
+  /**
+   * Gets the buttons of a specific joystick.
+   *
+   * @param joystickNum the joystick number
+   * @param count the count of buttons
+   * @return The joystick button values
+   * @see "HAL_GetJoystickButtons"
+   */
   public static native int getJoystickButtons(byte joystickNum, ByteBuffer count);
 
+  /**
+   * Get all joystick data.
+   *
+   * @param axesArray all joystick axes
+   * @param rawAxesArray all joystick axes as int
+   * @param povsArray all povs
+   * @param buttonsAndMetadata array of long joystick axes count, long joystick povs count, long
+   *     jostick buttons count, long joystick buttons values
+   * @see "HAL_GetAllJoystickData"
+   */
   public static native void getAllJoystickData(
       float[] axesArray, byte[] rawAxesArray, short[] povsArray, long[] buttonsAndMetadata);
 
+  /**
+   * Set joystick outputs.
+   *
+   * @param joystickNum the joystick number
+   * @param outputs bitmask of outputs, 1 for on 0 for off
+   * @param leftRumble the left rumble value (0-FFFF)
+   * @param rightRumble the right rumble value (0-FFFF)
+   * @return the error code, or 0 for success
+   * @see "HAL_SetJoystickOutputs"
+   */
   public static native int setJoystickOutputs(
       byte joystickNum, int outputs, short leftRumble, short rightRumble);
 
+  /**
+   * Gets whether a specific joystick is considered to be an XBox controller.
+   *
+   * @param joystickNum the joystick number
+   * @return 1 if xbox, 0 otherwise
+   * @see "HAL_GetJoystickIsXbox"
+   */
   public static native int getJoystickIsXbox(byte joystickNum);
 
+  /**
+   * Gets the type of joystick connected.
+   *
+   * <p>This is device specific, and different depending on what system input type the joystick
+   * uses.
+   *
+   * @param joystickNum the joystick number
+   * @return the enumerated joystick type
+   * @see "HAL_GetJoystickType"
+   */
   public static native int getJoystickType(byte joystickNum);
 
+  /**
+   * Gets the name of a joystick.
+   *
+   * <p>The returned array must be freed with HAL_FreeJoystickName.
+   *
+   * @param joystickNum the joystick number
+   * @return the joystick name
+   * @see "HAL_GetJoystickName"
+   */
   public static native String getJoystickName(byte joystickNum);
 
+  /**
+   * Gets the type of a specific joystick axis.
+   *
+   * <p>This is device specific, and different depending on what system input type the joystick
+   * uses.
+   *
+   * @param joystickNum the joystick number
+   * @param axis the axis number
+   * @return the enumerated axis type
+   * @see "HAL_GetJoystickAxisType"
+   */
   public static native int getJoystickAxisType(byte joystickNum, byte axis);
 
+  /**
+   * Returns the approximate match time.
+   *
+   * <p>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).
+   *
+   * <p>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).
+   *
+   * <p>The Practice Match function of the DS approximates the behavior seen on the field.
+   *
+   * @return time remaining in current match period (auto or teleop)
+   * @see "HAL_GetMatchTime"
+   */
   public static native double getMatchTime();
 
+  /**
+   * Gets info about a specific match.
+   *
+   * @param info the match info to populate
+   * @return the error code, or 0 for success
+   * @see "HAL_GetMatchInfo"
+   */
   public static native int getMatchInfo(MatchInfoData info);
 
+  /**
+   * Sends an error to the driver station.
+   *
+   * @param isError true for error, false for warning
+   * @param errorCode the error code
+   * @param isLVCode true for a LV error code, false for a standard error code
+   * @param details the details of the error
+   * @param location the file location of the error
+   * @param callStack the callstack of the error
+   * @param printMsg true to print the error message to stdout as well as to the DS
+   * @return the error code, or 0 for success
+   * @see "HAL_SendError"
+   */
   public static native int sendError(
       boolean isError,
       int errorCode,
@@ -123,14 +345,31 @@
       String callStack,
       boolean printMsg);
 
+  /**
+   * Sends a line to the driver station console.
+   *
+   * @param line the line to send
+   * @return the error code, or 0 for success
+   */
   public static native int sendConsoleLine(String line);
 
-  public static native void refreshDSData();
+  /**
+   * Refresh the DS control word.
+   *
+   * @return true if updated
+   * @see "HAL_RefreshDSData"
+   */
+  public static native boolean refreshDSData();
 
   public static native void provideNewDataEventHandle(int handle);
 
   public static native void removeNewDataEventHandle(int handle);
 
+  /**
+   * Gets if outputs are enabled by the control system.
+   *
+   * @return true if outputs are enabled
+   */
   public static native boolean getOutputsActive();
 
   private DriverStationJNI() {}
diff --git a/hal/src/main/java/edu/wpi/first/hal/DutyCycleJNI.java b/hal/src/main/java/edu/wpi/first/hal/DutyCycleJNI.java
index f2737d8..1e7dfa0 100644
--- a/hal/src/main/java/edu/wpi/first/hal/DutyCycleJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/DutyCycleJNI.java
@@ -4,18 +4,78 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * DutyCycle HAL JNI functions.
+ *
+ * @see "DutyCycle.h"
+ */
 public class DutyCycleJNI extends JNIWrapper {
+  /**
+   * Initialize a DutyCycle input.
+   *
+   * @param digitalSourceHandle the digital source to use (either a Digital Handle or a
+   *     AnalogTrigger Handle)
+   * @param analogTriggerType the analog trigger type of the source if it is an analog trigger
+   * @return the created duty cycle handle
+   * @see "HAL_InitializeDutyCycle"
+   */
   public static native int initialize(int digitalSourceHandle, int analogTriggerType);
 
+  /**
+   * Free a DutyCycle.
+   *
+   * @param handle the duty cycle handle
+   * @see "HAL_FreeDutyCycle"
+   */
   public static native void free(int handle);
 
+  /**
+   * Get the frequency of the duty cycle signal.
+   *
+   * @param handle the duty cycle handle
+   * @return frequency in Hertz
+   * @see "HAL_GetDutyCycleFrequency"
+   */
   public static native int getFrequency(int handle);
 
+  /**
+   * Get the output ratio of the duty cycle signal.
+   *
+   * <p>0 means always low, 1 means always high.
+   *
+   * @param handle the duty cycle handle
+   * @return output ratio between 0 and 1
+   * @see "HAL_GetDutyCycleOutput"
+   */
   public static native double getOutput(int handle);
 
+  /**
+   * Get the raw high time of the duty cycle signal.
+   *
+   * @param handle the duty cycle handle
+   * @return high time of last pulse in nanoseconds
+   * @see "HAL_GetDutyCycleHighTime"
+   */
   public static native int getHighTime(int handle);
 
+  /**
+   * Get the scale factor of the output.
+   *
+   * <p>An output equal to this value is always high, and then linearly scales down to 0. Divide a
+   * raw result by this in order to get the percentage between 0 and 1. Used by DMA.
+   *
+   * @param handle the duty cycle handle
+   * @return the output scale factor
+   * @see "HAL_GetDutyCycleOutputScaleFactor"
+   */
   public static native int getOutputScaleFactor(int handle);
 
+  /**
+   * Get the FPGA index for the DutyCycle.
+   *
+   * @param handle the duty cycle handle
+   * @return the FPGA index
+   * @see "HAL_GetDutyCycleFPGAIndex"
+   */
   public static native int getFPGAIndex(int handle);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/EncoderJNI.java b/hal/src/main/java/edu/wpi/first/hal/EncoderJNI.java
index 50ecc91..d219db0 100644
--- a/hal/src/main/java/edu/wpi/first/hal/EncoderJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/EncoderJNI.java
@@ -4,7 +4,24 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Encoder JNI Functions.
+ *
+ * @see "hal/Encoder.h"
+ */
 public class EncoderJNI extends JNIWrapper {
+  /**
+   * Initializes an encoder.
+   *
+   * @param digitalSourceHandleA the A source handle (either a digital or analog trigger)
+   * @param analogTriggerTypeA the analog trigger type of the A source if it is an analog trigger
+   * @param digitalSourceHandleB the B source handle (either a digital or analog trigger)
+   * @param analogTriggerTypeB the analog trigger type of the B source if it is an analog trigger
+   * @param reverseDirection true to reverse the counting direction from standard, otherwise false
+   * @param encodingType the encoding type
+   * @return the created encoder handle
+   * @see "HAL_InitializeEncoder"
+   */
   public static native int initializeEncoder(
       int digitalSourceHandleA,
       int analogTriggerTypeA,
@@ -13,50 +30,249 @@
       boolean reverseDirection,
       int encodingType);
 
+  /**
+   * Frees an encoder.
+   *
+   * @param encoderHandle the encoder handle
+   * @see "HAL_FreeEncoder"
+   */
   public static native void freeEncoder(int encoderHandle);
 
+  /**
+   * Indicates the encoder is used by a simulated device.
+   *
+   * @param handle the encoder handle
+   * @param device simulated device handle
+   * @see "HAL_SetEncoderSimDevice"
+   */
   public static native void setEncoderSimDevice(int handle, int device);
 
+  /**
+   * Gets the current counts of the encoder after encoding type scaling.
+   *
+   * <p>This is scaled by the value passed during initialization to encodingType.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the current scaled count
+   * @see "HAL_GetEncoder"
+   */
   public static native int getEncoder(int encoderHandle);
 
+  /**
+   * Gets the raw counts of the encoder.
+   *
+   * <p>This is not scaled by any values.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the raw encoder count
+   * @see "HAL_GetEncoderRaw"
+   */
   public static native int getEncoderRaw(int encoderHandle);
 
+  /**
+   * Gets the encoder scale value.
+   *
+   * <p>This is set by the value passed during initialization to encodingType.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the encoder scale value
+   * @see "HAL_GetEncoderEncodingScale"
+   */
   public static native int getEncodingScaleFactor(int encoderHandle);
 
+  /**
+   * Reads the current encoder value.
+   *
+   * <p>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.
+   *
+   * @param encoderHandle the encoder handle
+   * @see "HAL_ResetEncoder"
+   */
   public static native void resetEncoder(int encoderHandle);
 
+  /**
+   * Gets the Period of the most recent count.
+   *
+   * <p>Returns the time interval of the most recent count. This can be used for velocity
+   * calculations to determine shaft speed.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the period of the last two pulses in units of seconds
+   * @see "HAL_GetEncoderPeriod"
+   */
   public static native double getEncoderPeriod(int encoderHandle);
 
+  /**
+   * Sets the maximum period where the device is still considered "moving".
+   *
+   * <p>Sets the maximum period where the device is considered moving. This value is used to
+   * determine the "stopped" state of the encoder using the getEncoderStopped method.
+   *
+   * @param encoderHandle the encoder handle
+   * @param maxPeriod the maximum period where the counted device is considered moving in seconds
+   * @see "HAL_SetEncoderMaxPeriod"
+   */
   public static native void setEncoderMaxPeriod(int encoderHandle, double maxPeriod);
 
+  /**
+   * Determines if the clock is stopped.
+   *
+   * <p>Determines 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 encoder) are
+   * assumed to be stopped and it returns true.
+   *
+   * @param encoderHandle the encoder handle
+   * @return true if the most recent encoder period exceeds the MaxPeriod value set by SetMaxPeriod
+   * @see "HAL_GetEncoderStopped"
+   */
   public static native boolean getEncoderStopped(int encoderHandle);
 
+  /**
+   * Gets the last direction the encoder value changed.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the last direction the encoder value changed
+   * @see "HAL_GetEncoderDirection"
+   */
   public static native boolean getEncoderDirection(int encoderHandle);
 
+  /**
+   * Gets the current distance traveled by the encoder.
+   *
+   * <p>This is the encoder count scaled by the distance per pulse set for the encoder.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the encoder distance (units are determined by the units passed to
+   *     setEncoderDistancePerPulse)
+   * @see "HAL_GetEncoderDistance"
+   */
   public static native double getEncoderDistance(int encoderHandle);
 
+  /**
+   * Gets the current rate of the encoder.
+   *
+   * <p>This is the encoder period scaled by the distance per pulse set for the encoder.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the encoder rate (units are determined by the units passed to
+   *     setEncoderDistancePerPulse, time value is seconds)
+   * @see "HAL_GetEncoderRate"
+   */
   public static native double getEncoderRate(int encoderHandle);
 
+  /**
+   * Sets the minimum rate to be considered moving by the encoder.
+   *
+   * <p>Units need to match what is set by setEncoderDistancePerPulse, with time as seconds.
+   *
+   * @param encoderHandle the encoder handle
+   * @param minRate the minimum rate to be considered moving (units are determined by the units
+   *     passed to setEncoderDistancePerPulse, time value is seconds)
+   * @see "HAL_SetEncoderMinRate"
+   */
   public static native void setEncoderMinRate(int encoderHandle, double minRate);
 
+  /**
+   * Sets the distance traveled per encoder pulse. This is used as a scaling factor for the rate and
+   * distance calls.
+   *
+   * @param encoderHandle the encoder handle
+   * @param distancePerPulse the distance traveled per encoder pulse (units user defined)
+   * @see "HAL_SetEncoderDistancePerPulse"
+   */
   public static native void setEncoderDistancePerPulse(int encoderHandle, double distancePerPulse);
 
+  /**
+   * Sets if to reverse the direction of the encoder.
+   *
+   * <p>Note that this is not a toggle. It is an absolute set.
+   *
+   * @param encoderHandle the encoder handle
+   * @param reverseDirection true to reverse the direction, false to not.
+   * @see "HAL_SetEncoderReverseDirection"
+   */
   public static native void setEncoderReverseDirection(int encoderHandle, boolean reverseDirection);
 
+  /**
+   * Sets the number of encoder samples to average when calculating encoder rate.
+   *
+   * @param encoderHandle the encoder handle
+   * @param samplesToAverage the number of samples to average
+   * @see "HAL_SetEncoderSamplesToAverage"
+   */
   public static native void setEncoderSamplesToAverage(int encoderHandle, int samplesToAverage);
 
+  /**
+   * Gets the current samples to average value.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the current samples to average value
+   * @see "HAL_GetEncoderSamplesToAverage"
+   */
   public static native int getEncoderSamplesToAverage(int encoderHandle);
 
+  /**
+   * Sets the source for an index pulse on the encoder.
+   *
+   * <p>The index pulse can be used to cause an encoder to reset based on an external input.
+   *
+   * @param encoderHandle the encoder handle
+   * @param digitalSourceHandle the index source handle (either a HAL_AnalogTriggerHandle or a
+   *     HAL_DigitalHandle)
+   * @param analogTriggerType the analog trigger type if the source is an analog trigger
+   * @param indexingType the index triggering type
+   * @see "HAL_SetEncoderIndexSource"
+   */
   public static native void setEncoderIndexSource(
       int encoderHandle, int digitalSourceHandle, int analogTriggerType, int indexingType);
 
+  /**
+   * Gets the FPGA index of the encoder.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the FPGA index of the encoder
+   * @see "HAL_GetEncoderFPGAIndex"
+   */
   public static native int getEncoderFPGAIndex(int encoderHandle);
 
+  /**
+   * Gets the encoder scale value.
+   *
+   * <p>This is set by the value passed during initialization to encodingType.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the encoder scale value
+   * @see "HAL_GetEncoderEncodingScale"
+   */
   public static native int getEncoderEncodingScale(int encoderHandle);
 
+  /**
+   * Gets the decoding scale factor of the encoder.
+   *
+   * <p>This is used to perform the scaling from raw to type scaled values.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the scale value for the encoder
+   * @see "HAL_GetEncoderDecodingScaleFactor"
+   */
   public static native double getEncoderDecodingScaleFactor(int encoderHandle);
 
+  /**
+   * Gets the user set distance per pulse of the encoder.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the set distance per pulse
+   * @see "HAL_GetEncoderDistancePerPulse"
+   */
   public static native double getEncoderDistancePerPulse(int encoderHandle);
 
+  /**
+   * Gets the encoding type of the encoder.
+   *
+   * @param encoderHandle the encoder handle
+   * @return the encoding type
+   * @see "HAL_GetEncoderEncodingType"
+   */
   public static native int getEncoderEncodingType(int encoderHandle);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/HAL.java b/hal/src/main/java/edu/wpi/first/hal/HAL.java
index 68e6ec8..d9eb8d5 100644
--- a/hal/src/main/java/edu/wpi/first/hal/HAL.java
+++ b/hal/src/main/java/edu/wpi/first/hal/HAL.java
@@ -8,18 +8,71 @@
 import java.util.List;
 
 /**
- * JNI Wrapper for HAL<br>
- * .
+ * JNI Wrapper for Hardware Abstraction Layer (HAL).
+ *
+ * @see "hal/HALBase.h"
+ * @see "hal/Main.h"
+ * @see "hal/FRCUsageReporting.h"
  */
 public final class HAL extends JNIWrapper {
+  /**
+   * Call this to start up HAL. This is required for robot programs.
+   *
+   * <p>This must be called before any other HAL functions. Failure to do so will result in
+   * undefined behavior, and likely segmentation faults. This means that any statically initialized
+   * variables in a program MUST call this function in their constructors if they want to use other
+   * HAL calls.
+   *
+   * <p>The common parameters are 500 for timeout and 0 for mode.
+   *
+   * <p>This function is safe to call from any thread, and as many times as you wish. It internally
+   * guards from any reentrancy.
+   *
+   * <p>The applicable modes are: 0: Try to kill an existing HAL from another program, if not
+   * successful, error. 1: Force kill a HAL from another program. 2: Just warn if another hal exists
+   * and cannot be killed. Will likely result in undefined behavior.
+   *
+   * @param timeout the initialization timeout (ms)
+   * @param mode the initialization mode (see remarks)
+   * @return true if initialization was successful, otherwise false.
+   * @see "HAL_Initialize"
+   */
   public static native boolean initialize(int timeout, int mode);
 
+  /**
+   * Call this to shut down HAL.
+   *
+   * <p>This must be called at termination of the robot program to avoid potential segmentation
+   * faults with simulation extensions at exit.
+   *
+   * @see "HAL_Shutdown"
+   */
   public static native void shutdown();
 
+  /**
+   * Returns true if HAL_SetMain() has been called.
+   *
+   * @return True if HAL_SetMain() has been called, false otherwise.
+   * @see "HAL_HasMain"
+   */
   public static native boolean hasMain();
 
+  /**
+   * Runs the main function provided to HAL_SetMain().
+   *
+   * <p>If HAL_SetMain() has not been called, simply sleeps until exitMain() is called.
+   *
+   * @see "HAL_RunMain"
+   */
   public static native void runMain();
 
+  /**
+   * Causes HAL_RunMain() to exit.
+   *
+   * <p>If HAL_SetMain() has been called, this calls the exit function provided to that function.
+   *
+   * @see "HAL_ExitMain"
+   */
   public static native void exitMain();
 
   private static native void simPeriodicBeforeNative();
@@ -113,22 +166,108 @@
     }
   }
 
+  /**
+   * Gets if the system is in a browned out state.
+   *
+   * @return true if the system is in a low voltage brown out, false otherwise
+   * @see "HAL_GetBrownedOut"
+   */
   public static native boolean getBrownedOut();
 
+  /**
+   * Gets if the system outputs are currently active.
+   *
+   * @return true if the system outputs are active, false if disabled
+   * @see "HAL_GetSystemActive"
+   */
   public static native boolean getSystemActive();
 
+  /**
+   * Gets the current state of the Robot Signal Light (RSL).
+   *
+   * @return The current state of the RSL- true if on, false if off
+   * @see "HAL_GetRSLState"
+   */
+  public static native boolean getRSLState();
+
+  /**
+   * Gets if the system time is valid.
+   *
+   * @return True if the system time is valid, false otherwise
+   * @see "HAL_GetSystemTimeValid"
+   */
+  public static native boolean getSystemTimeValid();
+
+  /**
+   * Gets a port handle for a specific channel and module.
+   *
+   * <p>This is expected to be used for PCMs, as the roboRIO does not work with modules anymore.
+   *
+   * <p>The created handle does not need to be freed.
+   *
+   * @param module the module number
+   * @param channel the channel number
+   * @return the created port
+   * @see "HAL_GetPortWithModule"
+   */
   public static native int getPortWithModule(byte module, byte channel);
 
+  /**
+   * Gets a port handle for a specific channel.
+   *
+   * <p>The created handle does not need to be freed.
+   *
+   * @param channel the channel number
+   * @return the created port
+   * @see "HAL_GetPort"
+   */
   public static native int getPort(byte channel);
 
+  /**
+   * Report the usage of a resource of interest.
+   *
+   * <p>Original signature: <code>uint32_t report(tResourceType, uint8_t, uint8_t, const
+   * char*)</code>
+   *
+   * @param resource one of the values in the tResourceType above.
+   * @param instanceNumber an index that identifies the resource instance.
+   * @see "HAL_Report"
+   */
   public static void report(int resource, int instanceNumber) {
     report(resource, instanceNumber, 0, "");
   }
 
+  /**
+   * Report the usage of a resource of interest.
+   *
+   * <p>Original signature: <code>uint32_t report(tResourceType, uint8_t, uint8_t, const
+   * char*)</code>
+   *
+   * @param resource one of the values in the tResourceType above.
+   * @param instanceNumber an index that identifies the resource instance.
+   * @param context an optional additional context number for some cases (such as module number).
+   *     Set to 0 to omit.
+   * @see "HAL_Report"
+   */
   public static void report(int resource, int instanceNumber, int context) {
     report(resource, instanceNumber, context, "");
   }
 
+  /**
+   * Report the usage of a resource of interest.
+   *
+   * <p>Original signature: <code>uint32_t report(tResourceType, uint8_t, uint8_t, const
+   * char*)</code>
+   *
+   * @param resource one of the values in the tResourceType above.
+   * @param instanceNumber an index that identifies the resource instance.
+   * @param context an optional additional context number for some cases (such as module number).
+   *     Set to 0 to omit.
+   * @param feature a string to be included describing features in use on a specific resource.
+   *     Setting the same resource more than once allows you to change the feature string.
+   * @return the index of the added value in NetComm
+   * @see "HAL_Report"
+   */
   public static int report(int resource, int instanceNumber, int context, String feature) {
     return DriverStationJNI.report(resource, instanceNumber, context, feature);
   }
diff --git a/hal/src/main/java/edu/wpi/first/hal/HALUtil.java b/hal/src/main/java/edu/wpi/first/hal/HALUtil.java
index 7c0f41a..11d9b4d 100644
--- a/hal/src/main/java/edu/wpi/first/hal/HALUtil.java
+++ b/hal/src/main/java/edu/wpi/first/hal/HALUtil.java
@@ -4,6 +4,11 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Hardware Abstraction Layer (HAL) Utilities JNI Functions.
+ *
+ * @see "hal/HALBase.h"
+ */
 public final class HALUtil extends JNIWrapper {
   public static final int NULL_PARAMETER = -1005;
   public static final int SAMPLE_RATE_TOO_HIGH = 1001;
@@ -18,26 +23,108 @@
   public static final int RUNTIME_ROBORIO2 = 1;
   public static final int RUNTIME_SIMULATION = 2;
 
+  /**
+   * Returns the FPGA Version number.
+   *
+   * <p>For now, expect this to be competition year.
+   *
+   * @return FPGA Version number.
+   * @see "HAL_GetFPGAVersion"
+   */
   public static native short getFPGAVersion();
 
+  /**
+   * Returns the FPGA Revision number.
+   *
+   * <p>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.
+   * @see "HAL_GetFPGARevision"
+   */
   public static native int getFPGARevision();
 
+  /**
+   * Returns the roboRIO serial number.
+   *
+   * @return The roboRIO serial number.
+   * @see "HAL_GetSerialNumber"
+   */
   public static native String getSerialNumber();
 
+  /**
+   * Returns the comments from the roboRIO web interface.
+   *
+   * @return The comments string.
+   * @see "HAL_GetComments"
+   */
   public static native String getComments();
 
+  /**
+   * Returns the team number configured for the robot controller.
+   *
+   * @return team number, or 0 if not found.
+   * @see "HAL_GetTeamNumber"
+   */
+  public static native int getTeamNumber();
+
+  /**
+   * Reads the microsecond-resolution timer on the FPGA.
+   *
+   * @return The current time in microseconds according to the FPGA (since FPGA reset).
+   */
   public static native long getFPGATime();
 
+  /**
+   * Returns the runtime type of the HAL.
+   *
+   * @return HAL Runtime Type
+   * @see RUNTIME_ROBORIO
+   * @see RUNTIME_ROBORIO2
+   * @see RUNTIME_SIMULATION
+   * @see "HAL_GetRuntimeType"
+   */
   public static native int getHALRuntimeType();
 
+  /**
+   * Gets the state of the "USER" button on the roboRIO.
+   *
+   * @return true if the button is currently pressed down
+   * @see "HAL_GetFPGAButton"
+   */
   public static native boolean getFPGAButton();
 
+  /**
+   * Gets the error message for a specific status code.
+   *
+   * @param code the status code
+   * @return the error message for the code. This does not need to be freed.
+   * @see "HAL_GetErrorMessage"
+   */
   public static native String getHALErrorMessage(int code);
 
+  /**
+   * Get the last HAL error code.
+   *
+   * @return error code
+   */
   public static native int getHALErrno();
 
+  /**
+   * Returns the textual description of the system error code.
+   *
+   * @param errno errno to get description of
+   * @return description of errno
+   * @see "std:strerror"
+   */
   public static native String getHALstrerror(int errno);
 
+  /**
+   * Gets the error message for the last HAL error.
+   *
+   * @return the error message for the code.
+   */
   public static String getHALstrerror() {
     return getHALstrerror(getHALErrno());
   }
diff --git a/hal/src/main/java/edu/wpi/first/hal/I2CJNI.java b/hal/src/main/java/edu/wpi/first/hal/I2CJNI.java
index 63f32a0..90e8ddb 100644
--- a/hal/src/main/java/edu/wpi/first/hal/I2CJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/I2CJNI.java
@@ -6,9 +6,38 @@
 
 import java.nio.ByteBuffer;
 
+/**
+ * I2C HAL JNI functions.
+ *
+ * @see "I2C.h"
+ */
 public class I2CJNI extends JNIWrapper {
+  /**
+   * Initializes the I2C port.
+   *
+   * <p>Opens the port if necessary and saves the handle. If opening the MXP port, also sets up the
+   * channel functions appropriately.
+   *
+   * @param port The port to open, 0 for the on-board, 1 for the MXP.
+   * @see "HAL_InitializeI2C"
+   */
   public static native void i2CInitialize(int port);
 
+  /**
+   * Generic I2C read/write transaction.
+   *
+   * <p>This is a lower-level interface to the I2C hardware giving you more control over each
+   * transaction.
+   *
+   * @param port The I2C port, 0 for the on-board, 1 for the MXP.
+   * @param address The address of the register on the device to be read/written.
+   * @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 &gt;= 0 on success or -1 on transfer abort.
+   * @see "HAL_TransactionI2C"
+   */
   public static native int i2CTransaction(
       int port,
       byte address,
@@ -17,6 +46,21 @@
       ByteBuffer dataReceived,
       byte receiveSize);
 
+  /**
+   * Generic I2C read/write transaction.
+   *
+   * <p>This is a lower-level interface to the I2C hardware giving you more control over each
+   * transaction.
+   *
+   * @param port The I2C port, 0 for the on-board, 1 for the MXP.
+   * @param address The address of the register on the device to be read/written.
+   * @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 &gt;= 0 on success or -1 on transfer abort.
+   * @see "HAL_TransactionI2C"
+   */
   public static native int i2CTransactionB(
       int port,
       byte address,
@@ -25,14 +69,70 @@
       byte[] dataReceived,
       byte receiveSize);
 
+  /**
+   * Executes a write transaction with the device.
+   *
+   * <p>Writes a single byte to a register on a device and wait until the transaction is complete.
+   *
+   * @param port The I2C port, 0 for the on-board, 1 for the MXP.
+   * @param address The address of the register on the device to be written.
+   * @param dataToSend The byte to write to the register on the device.
+   * @param sendSize Number of bytes to send.
+   * @return &gt;= 0 on success or -1 on transfer abort.
+   * @see "HAL_WriteI2C"
+   */
   public static native int i2CWrite(int port, byte address, ByteBuffer dataToSend, byte sendSize);
 
+  /**
+   * Executes a write transaction with the device.
+   *
+   * <p>Writes a single byte to a register on a device and wait until the transaction is complete.
+   *
+   * @param port The I2C port, 0 for the on-board, 1 for the MXP.
+   * @param address The address of the register on the device to be written.
+   * @param dataToSend The byte to write to the register on the device.
+   * @param sendSize Number of bytes to send.
+   * @return &gt;= 0 on success or -1 on transfer abort.
+   * @see "HAL_WriteI2C"
+   */
   public static native int i2CWriteB(int port, byte address, byte[] dataToSend, byte sendSize);
 
+  /**
+   * Executes a read transaction with the device.
+   *
+   * <p>Reads 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 port The I2C port, 0 for the on-board, 1 for the MXP.
+   * @param address The register to read first in the transaction.
+   * @param dataReceived A ByteBuffer to store the data read from the device.
+   * @param receiveSize The number of bytes to read in the transaction.
+   * @return &gt;= 0 on success or -1 on transfer abort.
+   * @see "HAL_ReadI2C"
+   */
   public static native int i2CRead(
       int port, byte address, ByteBuffer dataReceived, byte receiveSize);
 
+  /**
+   * Executes a read transaction with the device.
+   *
+   * <p>Reads 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 port The I2C port, 0 for the on-board, 1 for the MXP.
+   * @param address The register to read first in the transaction.
+   * @param dataReceived A byte array to store the data read from the device.
+   * @param receiveSize The number of bytes to read in the transaction.
+   * @return &gt;= 0 on success or -1 on transfer abort.
+   * @see "HAL_ReadI2C"
+   */
   public static native int i2CReadB(int port, byte address, byte[] dataReceived, byte receiveSize);
 
+  /**
+   * Closes an I2C port.
+   *
+   * @param port The I2C port, 0 for the on-board, 1 for the MXP.
+   * @see "HAL_CloseI2C"
+   */
   public static native void i2CClose(int port);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/InterruptJNI.java b/hal/src/main/java/edu/wpi/first/hal/InterruptJNI.java
index 7dc2e6d..c605435 100644
--- a/hal/src/main/java/edu/wpi/first/hal/InterruptJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/InterruptJNI.java
@@ -4,28 +4,113 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Interrupt HAL JNI functions.
+ *
+ * @see "hal/Interrupts.h"
+ */
 public class InterruptJNI extends JNIWrapper {
   public static final int HalInvalidHandle = 0;
 
+  /**
+   * Initializes an interrupt.
+   *
+   * @return the created interrupt handle
+   * @see "HAL_InitializeInterrupts"
+   */
   public static native int initializeInterrupts();
 
+  /**
+   * Frees an interrupt.
+   *
+   * @param interruptHandle the interrupt handle
+   * @see "HAL_CleanInterrupts"
+   */
   public static native void cleanInterrupts(int interruptHandle);
 
+  /**
+   * Waits for the defined interrupt to occur.
+   *
+   * @param interruptHandle the interrupt handle
+   * @param timeout timeout in seconds
+   * @param ignorePrevious if true, ignore interrupts that happened before waitForInterrupt was
+   *     called
+   * @return the mask of interrupts that fired
+   * @see "HAL_WaitForInterrupt"
+   */
   public static native long waitForInterrupt(
       int interruptHandle, double timeout, boolean ignorePrevious);
 
+  /**
+   * Waits for any interrupt covered by the mask to occur.
+   *
+   * @param interruptHandle the interrupt handle to use for the context
+   * @param mask the mask of interrupts to wait for
+   * @param timeout timeout in seconds
+   * @param ignorePrevious if true, ignore interrupts that happened before waitForInterrupt was
+   *     called
+   * @return the mask of interrupts that fired
+   * @see "HAL_WaitForMultipleInterrupts"
+   */
   public static native long waitForMultipleInterrupts(
       int interruptHandle, long mask, double timeout, boolean ignorePrevious);
 
+  /**
+   * Returns the timestamp for the rising interrupt that occurred most recently.
+   *
+   * <p>This is in the same time domain as getFPGATime(). It only contains the bottom 32 bits of the
+   * timestamp. If your robot has been running for over 1 hour, you will need to fill in the upper
+   * 32 bits yourself.
+   *
+   * @param interruptHandle the interrupt handle
+   * @return timestamp in microseconds since FPGA Initialization
+   */
   public static native long readInterruptRisingTimestamp(int interruptHandle);
 
+  /**
+   * Returns the timestamp for the falling interrupt that occurred most recently.
+   *
+   * <p>This is in the same time domain as getFPGATime(). It only contains the bottom 32 bits of the
+   * timestamp. If your robot has been running for over 1 hour, you will need to fill in the upper
+   * 32 bits yourself.
+   *
+   * @param interruptHandle the interrupt handle
+   * @return timestamp in microseconds since FPGA Initialization
+   */
   public static native long readInterruptFallingTimestamp(int interruptHandle);
 
+  /**
+   * Requests interrupts on a specific digital source.
+   *
+   * @param interruptHandle the interrupt handle
+   * @param digitalSourceHandle the digital source handle (either a HAL_AnalogTriggerHandle or a
+   *     HAL_DigitalHandle)
+   * @param analogTriggerType the trigger type if the source is an AnalogTrigger
+   * @see "HAL_RequestInterrupts"
+   */
   public static native void requestInterrupts(
       int interruptHandle, int digitalSourceHandle, int analogTriggerType);
 
+  /**
+   * Sets the edges to trigger the interrupt on.
+   *
+   * <p>Note that both edges triggered is a valid configuration.
+   *
+   * @param interruptHandle the interrupt handle
+   * @param risingEdge true for triggering on rising edge
+   * @param fallingEdge true for triggering on falling edge
+   * @see "HAL_SetInterruptUpSourceEdge"
+   */
   public static native void setInterruptUpSourceEdge(
       int interruptHandle, boolean risingEdge, boolean fallingEdge);
 
+  /**
+   * Releases a waiting interrupt.
+   *
+   * <p>This will release both rising and falling waiters.
+   *
+   * @param interruptHandle the interrupt handle to release
+   * @see "HAL_ReleaseWaitingInterrupt"
+   */
   public static native void releaseWaitingInterrupt(int interruptHandle);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/NotifierJNI.java b/hal/src/main/java/edu/wpi/first/hal/NotifierJNI.java
index 648e8a2..5620f03 100644
--- a/hal/src/main/java/edu/wpi/first/hal/NotifierJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/NotifierJNI.java
@@ -9,22 +9,34 @@
  *
  * <p>This class is not meant for direct use by teams. Instead, the edu.wpi.first.wpilibj.Notifier
  * class, which corresponds to the C++ Notifier class, should be used.
+ *
+ * @see "hal/Notifier.h"
  */
 public class NotifierJNI extends JNIWrapper {
   /**
-   * Initializes the notifier.
+   * Initializes a notifier.
    *
-   * @return True on success.
+   * <p>A notifier is an FPGA controller timer that triggers at requested intervals based on the
+   * FPGA time. This can be used to make precise control loops.
+   *
+   * @return the created notifier
+   * @see "HAL_InitializeNotifier"
    */
   public static native int initializeNotifier();
 
   /**
    * Sets the HAL notifier thread priority.
    *
+   * <p>The HAL notifier thread is responsible for managing the FPGA's notifier interrupt and waking
+   * up user's Notifiers when it's their time to run. Giving the HAL notifier thread real-time
+   * priority helps ensure the user's real-time Notifiers, if any, are notified to run in a timely
+   * manner.
+   *
    * @param realTime Set to true to set a real-time priority, false for standard priority.
    * @param priority Priority to set the thread to. For real-time, this is 1-99 with 99 being
    *     highest. For non-real-time, this is forced to 0. See "man 7 sched" for more details.
    * @return True on success.
+   * @see "HAL_SetNotifierThreadPriority"
    */
   public static native boolean setHALThreadPriority(boolean realTime, int priority);
 
@@ -33,44 +45,60 @@
    *
    * @param notifierHandle Notifier handle.
    * @param name Notifier name.
+   * @see "HAL_SetNotifierName"
    */
   public static native void setNotifierName(int notifierHandle, String name);
 
   /**
-   * Wakes up the waiter with time=0. Note: after this function is called, all calls to
-   * waitForNotifierAlarm() will immediately start returning 0.
+   * Stops a notifier from running.
    *
-   * @param notifierHandle Notifier handle.
+   * <p>This will cause any call into waitForNotifierAlarm to return with time = 0.
+   *
+   * @param notifierHandle the notifier handle
+   * @see "HAL_StopNotifier"
    */
   public static native void stopNotifier(int notifierHandle);
 
   /**
-   * Deletes the notifier object when we are done with it.
+   * Cleans a notifier.
    *
-   * @param notifierHandle Notifier handle.
+   * <p>Note this also stops a notifier if it is already running.
+   *
+   * @param notifierHandle the notifier handle
+   * @see "HAL_CleanNotifier"
    */
   public static native void cleanNotifier(int notifierHandle);
 
   /**
-   * Sets the notifier to wake up the waiter at triggerTime microseconds.
+   * Updates the trigger time for a notifier.
    *
-   * @param notifierHandle Notifier handle.
-   * @param triggerTime Trigger time in microseconds.
+   * <p>Note that this time is an absolute time relative to getFPGATime()
+   *
+   * @param notifierHandle the notifier handle
+   * @param triggerTime the updated trigger time
+   * @see "HAL_UpdateNotifierAlarm"
    */
   public static native void updateNotifierAlarm(int notifierHandle, long triggerTime);
 
   /**
-   * Cancels any pending wakeups set by updateNotifierAlarm(). Does NOT wake up any waiters.
+   * Cancels the next notifier alarm.
    *
-   * @param notifierHandle Notifier handle.
+   * <p>This does not cause waitForNotifierAlarm to return.
+   *
+   * @param notifierHandle the notifier handle
+   * @see "HAL_CancelNotifierAlarm"
    */
   public static native void cancelNotifierAlarm(int notifierHandle);
 
   /**
-   * Block until woken up by an alarm (or stop).
+   * Waits for the next alarm for the specific notifier.
    *
-   * @param notifierHandle Notifier handle.
-   * @return Time when woken up.
+   * <p>This is a blocking call until either the time elapses or stopNotifier gets called. If the
+   * latter occurs, this function will return zero and any loops using this function should exit.
+   * Failing to do so can lead to use-after-frees.
+   *
+   * @param notifierHandle the notifier handle
+   * @return the FPGA time the notifier returned
    */
   public static native long waitForNotifierAlarm(int notifierHandle);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/PWMConfigDataResult.java b/hal/src/main/java/edu/wpi/first/hal/PWMConfigDataResult.java
index ac3c8f94..0ec46dd 100644
--- a/hal/src/main/java/edu/wpi/first/hal/PWMConfigDataResult.java
+++ b/hal/src/main/java/edu/wpi/first/hal/PWMConfigDataResult.java
@@ -15,18 +15,18 @@
     this.min = min;
   }
 
-  /** The maximum PWM value. */
+  /** The maximum PWM value in microseconds. */
   public int max;
 
-  /** The deadband maximum PWM value. */
+  /** The deadband maximum PWM value in microseconds. */
   public int deadbandMax;
 
-  /** The center PWM value. */
+  /** The center PWM value in microseconds. */
   public int center;
 
-  /** The deadband minimum PWM value. */
+  /** The deadband minimum PWM value in microseconds. */
   public int deadbandMin;
 
-  /** The minimum PWM value. */
+  /** The minimum PWM value in microseconds. */
   public int min;
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/PWMJNI.java b/hal/src/main/java/edu/wpi/first/hal/PWMJNI.java
index 1ed562c..dc2abc1 100644
--- a/hal/src/main/java/edu/wpi/first/hal/PWMJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/PWMJNI.java
@@ -11,7 +11,7 @@
 
   public static native void freePWMPort(int pwmPortHandle);
 
-  public static native void setPWMConfigRaw(
+  public static native void setPWMConfigMicroseconds(
       int pwmPortHandle,
       int maxPwm,
       int deadbandMaxPwm,
@@ -19,27 +19,19 @@
       int deadbandMinPwm,
       int minPwm);
 
-  public static native void setPWMConfig(
-      int pwmPortHandle,
-      double maxPwm,
-      double deadbandMaxPwm,
-      double centerPwm,
-      double deadbandMinPwm,
-      double minPwm);
-
-  public static native PWMConfigDataResult getPWMConfigRaw(int pwmPortHandle);
+  public static native PWMConfigDataResult getPWMConfigMicroseconds(int pwmPortHandle);
 
   public static native void setPWMEliminateDeadband(int pwmPortHandle, boolean eliminateDeadband);
 
   public static native boolean getPWMEliminateDeadband(int pwmPortHandle);
 
-  public static native void setPWMRaw(int pwmPortHandle, short value);
+  public static native void setPulseTimeMicroseconds(int pwmPortHandle, int microsecondPulseTime);
 
   public static native void setPWMSpeed(int pwmPortHandle, double speed);
 
   public static native void setPWMPosition(int pwmPortHandle, double position);
 
-  public static native short getPWMRaw(int pwmPortHandle);
+  public static native int getPulseTimeMicroseconds(int pwmPortHandle);
 
   public static native double getPWMSpeed(int pwmPortHandle);
 
@@ -49,5 +41,7 @@
 
   public static native void latchPWMZero(int pwmPortHandle);
 
+  public static native void setAlwaysHighMode(int pwmPortHandle);
+
   public static native void setPWMPeriodScale(int pwmPortHandle, int squelchMask);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/PortsJNI.java b/hal/src/main/java/edu/wpi/first/hal/PortsJNI.java
index b4bd6cf..20f9b42 100644
--- a/hal/src/main/java/edu/wpi/first/hal/PortsJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/PortsJNI.java
@@ -4,48 +4,185 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Ports HAL JNI functions.
+ *
+ * @see "hal/Ports.h"
+ */
 public class PortsJNI extends JNIWrapper {
+  /**
+   * Gets the number of analog accumulators in the current system.
+   *
+   * @return the number of analog accumulators
+   * @see "HAL_GetNumAccumulators"
+   */
   public static native int getNumAccumulators();
 
+  /**
+   * Gets the number of analog triggers in the current system.
+   *
+   * @return the number of analog triggers
+   * @see "HAL_GetNumAnalogTriggers"
+   */
   public static native int getNumAnalogTriggers();
 
+  /**
+   * Gets the number of analog inputs in the current system.
+   *
+   * @return the number of analog inputs
+   * @see "HAL_GetNumAnalogInputs"
+   */
   public static native int getNumAnalogInputs();
 
+  /**
+   * Gets the number of analog outputs in the current system.
+   *
+   * @return the number of analog outputs
+   * @see "HAL_GetNumAnalogOutputs"
+   */
   public static native int getNumAnalogOutputs();
 
+  /**
+   * Gets the number of counters in the current system.
+   *
+   * @return the number of counters
+   * @see "HAL_GetNumCounters"
+   */
   public static native int getNumCounters();
 
+  /**
+   * Gets the number of digital headers in the current system.
+   *
+   * @return the number of digital headers
+   * @see "HAL_GetNumDigitalHeaders"
+   */
   public static native int getNumDigitalHeaders();
 
+  /**
+   * Gets the number of PWM headers in the current system.
+   *
+   * @return the number of PWM headers
+   * @see "HAL_GetNumPWMHeaders"
+   */
   public static native int getNumPWMHeaders();
 
+  /**
+   * Gets the number of digital channels in the current system.
+   *
+   * @return the number of digital channels
+   * @see "HAL_GetNumDigitalChannels"
+   */
   public static native int getNumDigitalChannels();
 
+  /**
+   * Gets the number of PWM channels in the current system.
+   *
+   * @return the number of PWM channels
+   * @see "HAL_GetNumPWMChannels"
+   */
   public static native int getNumPWMChannels();
 
+  /**
+   * Gets the number of digital IO PWM outputs in the current system.
+   *
+   * @return the number of digital IO PWM outputs
+   * @see "HAL_GetNumDigitalPWMOutputs"
+   */
   public static native int getNumDigitalPWMOutputs();
 
+  /**
+   * Gets the number of quadrature encoders in the current system.
+   *
+   * @return the number of quadrature encoders
+   * @see "HAL_GetNumEncoders"
+   */
   public static native int getNumEncoders();
 
+  /**
+   * Gets the number of interrupts in the current system.
+   *
+   * @return the number of interrupts
+   * @see "HAL_GetNumInterrupts"
+   */
   public static native int getNumInterrupts();
 
+  /**
+   * Gets the number of relay channels in the current system.
+   *
+   * @return the number of relay channels
+   * @see "HAL_GetNumRelayChannels"
+   */
   public static native int getNumRelayChannels();
 
+  /**
+   * Gets the number of relay headers in the current system.
+   *
+   * @return the number of relay headers
+   * @see "HAL_GetNumRelayHeaders"
+   */
   public static native int getNumRelayHeaders();
 
+  /**
+   * Gets the number of PCM modules in the current system.
+   *
+   * @return the number of PCM modules
+   * @see "HAL_GetNumCTREPCMModules"
+   */
   public static native int getNumCTREPCMModules();
 
+  /**
+   * Gets the number of solenoid channels in the current system.
+   *
+   * @return the number of solenoid channels
+   * @see "HAL_GetNumCTRESolenoidChannels"
+   */
   public static native int getNumCTRESolenoidChannels();
 
+  /**
+   * Gets the number of PDP modules in the current system.
+   *
+   * @return the number of PDP modules
+   * @see "HAL_GetNumCTREPDPModules"
+   */
   public static native int getNumCTREPDPModules();
 
+  /**
+   * Gets the number of PDP channels in the current system.
+   *
+   * @return the number of PDP channels
+   * @see "HAL_GetNumCTREPDPChannels"
+   */
   public static native int getNumCTREPDPChannels();
 
+  /**
+   * Gets the number of PDH modules in the current system.
+   *
+   * @return the number of PDH modules
+   * @see "HAL_GetNumREVPDHModules"
+   */
   public static native int getNumREVPDHModules();
 
+  /**
+   * Gets the number of PDH channels in the current system.
+   *
+   * @return the number of PDH channels
+   * @see "HAL_GetNumREVPDHChannels"
+   */
   public static native int getNumREVPDHChannels();
 
+  /**
+   * Gets the number of PH modules in the current system.
+   *
+   * @return the number of PH modules
+   * @see "HAL_GetNumREVPHModules"
+   */
   public static native int getNumREVPHModules();
 
+  /**
+   * Gets the number of PH channels in the current system.
+   *
+   * @return the number of PH channels
+   * @see "HAL_GetNumREVPHChannels"
+   */
   public static native int getNumREVPHChannels();
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/PowerDistributionJNI.java b/hal/src/main/java/edu/wpi/first/hal/PowerDistributionJNI.java
index 8280f93..bc7060d 100644
--- a/hal/src/main/java/edu/wpi/first/hal/PowerDistributionJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/PowerDistributionJNI.java
@@ -4,69 +4,282 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Power Distribution JNI Functions.
+ *
+ * @see "hal/PowerDistribution.h"
+ */
 public class PowerDistributionJNI extends JNIWrapper {
   public static final int AUTOMATIC_TYPE = 0;
   public static final int CTRE_TYPE = 1;
   public static final int REV_TYPE = 2;
   public static final int DEFAULT_MODULE = -1;
 
+  /**
+   * Initializes a Power Distribution Panel.
+   *
+   * @param module the module number to initialize
+   * @param type the type of module to initialize
+   * @return the created PowerDistribution handle
+   * @see "HAL_InitializePowerDistribution"
+   */
   public static native int initialize(int module, int type);
 
+  /**
+   * Cleans a PowerDistribution module.
+   *
+   * @param handle the module handle
+   * @see "HAL_CleanPowerDistribution"
+   */
   public static native void free(int handle);
 
+  /**
+   * Gets the module number for a specific handle.
+   *
+   * @param handle the module handle
+   * @return the module number
+   * @see "HAL_GetPowerDistributionModuleNumber"
+   */
   public static native int getModuleNumber(int handle);
 
+  /**
+   * Checks if a PowerDistribution module is valid.
+   *
+   * @param module the module to check
+   * @param type the type of module
+   * @return true if the module is valid, otherwise false
+   * @see "HAL_CheckPowerDistributionModule"
+   */
   public static native boolean checkModule(int module, int type);
 
+  /**
+   * Checks if a PowerDistribution channel is valid.
+   *
+   * @param handle the module handle
+   * @param channel the channel to check
+   * @return true if the channel is valid, otherwise false
+   * @see "HAL_CheckPowerDistributionChannel"
+   */
   public static native boolean checkChannel(int handle, int channel);
 
+  /**
+   * Gets the type of PowerDistribution module.
+   *
+   * @param handle the module handle
+   * @return the type of module
+   * @see "HAL_GetPowerDistributionType"
+   */
   public static native int getType(int handle);
 
+  /**
+   * Gets the number of channels for this handle.
+   *
+   * @param handle the handle
+   * @return number of channels
+   * @see "HAL_GetPowerDistributionNumChannels"
+   */
   public static native int getNumChannels(int handle);
 
+  /**
+   * Gets the temperature of the PowerDistribution.
+   *
+   * @param handle the module handle
+   * @return the module temperature (celsius)
+   * @see "HAL_GetPowerDistributionTemperature"
+   */
   public static native double getTemperature(int handle);
 
+  /**
+   * Gets the PowerDistribution input voltage.
+   *
+   * @param handle the module handle
+   * @return the input voltage (volts)
+   * @see "HAL_GetPowerDistributionVoltage"
+   */
   public static native double getVoltage(int handle);
 
+  /**
+   * Gets the current of a specific PowerDistribution channel.
+   *
+   * @param handle the module handle
+   * @param channel the channel
+   * @return the channel current (amps)
+   * @see "HAL_GetPowerDistributionChannelCurrent"
+   */
   public static native double getChannelCurrent(int handle, int channel);
 
+  /**
+   * Gets the current of all channels on the PowerDistribution.
+   *
+   * <p>The array must be large enough to hold all channels.
+   *
+   * @param handle the module handle
+   * @param currents the currents
+   * @see "HAL_GetPowerDistributionAllChannelCurrents"
+   */
   public static native void getAllCurrents(int handle, double[] currents);
 
+  /**
+   * Gets the total current of the PowerDistribution.
+   *
+   * @param handle the module handle
+   * @return the total current (amps)
+   * @see "HAL_GetPowerDistributionTotalCurrent"
+   */
   public static native double getTotalCurrent(int handle);
 
+  /**
+   * Gets the total power of the PowerDistribution.
+   *
+   * @param handle the module handle
+   * @return the total power (watts)
+   * @see "HAL_GetPowerDistributionTotalPower"
+   */
   public static native double getTotalPower(int handle);
 
+  /**
+   * Gets the total energy of the PowerDistribution.
+   *
+   * @param handle the module handle
+   * @return the total energy (joules)
+   * @see "HAL_GetPowerDistributionTotalEnergy"
+   */
   public static native double getTotalEnergy(int handle);
 
+  /**
+   * Resets the PowerDistribution accumulated energy.
+   *
+   * @param handle the module handle
+   * @see "HAL_ClearPowerDistributionStickyFaults"
+   */
   public static native void resetTotalEnergy(int handle);
 
+  /**
+   * Clears any PowerDistribution sticky faults.
+   *
+   * @param handle the module handle
+   * @see "HAL_ClearPowerDistributionStickyFaults"
+   */
   public static native void clearStickyFaults(int handle);
 
+  /**
+   * Returns true if switchable channel is powered on.
+   *
+   * <p>This is a REV PDH-specific function. This function will no-op on CTRE PDP.
+   *
+   * @param handle the module handle
+   * @return the state of the switchable channel
+   * @see "HAL_GetPowerDistributionSwitchableChannel"
+   */
   public static native boolean getSwitchableChannel(int handle);
 
+  /**
+   * Power on/off switchable channel.
+   *
+   * <p>This is a REV PDH-specific function. This function will no-op on CTRE PDP.
+   *
+   * @param handle the module handle
+   * @param enabled true to turn on switchable channel
+   * @see "HAL_SetPowerDistributionSwitchableChannel"
+   */
   public static native void setSwitchableChannel(int handle, boolean enabled);
 
+  /**
+   * Gets the PowerDistribution input voltage without throwing any errors.
+   *
+   * @param handle the module handle
+   * @return the input voltage (volts)
+   * @see "HAL_GetPowerDistributionVoltage"
+   */
   public static native double getVoltageNoError(int handle);
 
+  /**
+   * Gets the current of a specific PowerDistribution channel without throwing any errors.
+   *
+   * @param handle the module handle
+   * @param channel the channel
+   * @return the channel current (amps)
+   * @see "HAL_GetPowerDistributionChannelCurrent"
+   */
   public static native double getChannelCurrentNoError(int handle, int channel);
 
+  /**
+   * Gets the total current of the PowerDistribution without throwing any errors.
+   *
+   * @param handle the module handle
+   * @return the total current (amps)
+   * @see "HAL_GetPowerDistributionTotalCurrent"
+   */
   public static native double getTotalCurrentNoError(int handle);
 
+  /**
+   * Returns true if switchable channel is powered on without throwing any errors.
+   *
+   * <p>This is a REV PDH-specific function. This function will no-op on CTRE PDP.
+   *
+   * @param handle the module handle
+   * @return the state of the switchable channel
+   * @see "HAL_GetPowerDistributionSwitchableChannel"
+   */
   public static native boolean getSwitchableChannelNoError(int handle);
 
+  /**
+   * Power on/off switchable channel without throwing any errors.
+   *
+   * <p>This is a REV PDH-specific function. This function will no-op on CTRE PDP.
+   *
+   * @param handle the module handle
+   * @param enabled true to turn on switchable channel
+   * @see "HAL_SetPowerDistributionSwitchableChannel"
+   */
   public static native void setSwitchableChannelNoError(int handle, boolean enabled);
 
+  /**
+   * Get the current faults of the PowerDistribution.
+   *
+   * @param handle the module handle
+   * @return the current faults
+   * @see "HAL_GetPowerDistributionFaults"
+   */
   public static native int getFaultsNative(int handle);
 
+  /**
+   * Get the current faults of the PowerDistribution.
+   *
+   * @param handle the module handle
+   * @return the current faults
+   * @see "HAL_GetPowerDistributionFaults"
+   */
   public static PowerDistributionFaults getFaults(int handle) {
     return new PowerDistributionFaults(getFaultsNative(handle));
   }
 
+  /**
+   * Gets the sticky faults of the PowerDistribution.
+   *
+   * @param handle the module handle
+   * @return the sticky faults
+   * @see "HAL_GetPowerDistributionStickyFaults"
+   */
   public static native int getStickyFaultsNative(int handle);
 
+  /**
+   * Gets the sticky faults of the PowerDistribution.
+   *
+   * @param handle the module handle
+   * @return the sticky faults
+   * @see "HAL_GetPowerDistributionStickyFaults"
+   */
   public static PowerDistributionStickyFaults getStickyFaults(int handle) {
     return new PowerDistributionStickyFaults(getStickyFaultsNative(handle));
   }
 
+  /**
+   * Get the version of the PowerDistribution.
+   *
+   * @param handle the module handle
+   * @return version
+   * @see "HAL_GetPowerDistributionVersion"
+   */
   public static native PowerDistributionVersion getVersion(int handle);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/PowerJNI.java b/hal/src/main/java/edu/wpi/first/hal/PowerJNI.java
index 0bea6ed..8dd9548 100644
--- a/hal/src/main/java/edu/wpi/first/hal/PowerJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/PowerJNI.java
@@ -4,36 +4,167 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Power HAL JNI Functions.
+ *
+ * @see "Power.h"
+ */
 public class PowerJNI extends JNIWrapper {
+  /**
+   * Gets the roboRIO input voltage.
+   *
+   * @return the input voltage (volts)
+   * @see "HAL_GetVinVoltage"
+   */
   public static native double getVinVoltage();
 
+  /**
+   * Gets the roboRIO input current.
+   *
+   * @return the input current (amps)
+   * @see "HAL_GetVinCurrent"
+   */
   public static native double getVinCurrent();
 
+  /**
+   * Gets the 6V rail voltage.
+   *
+   * @return the 6V rail voltage (volts)
+   * @see "HAL_GetUserVoltage6V"
+   */
   public static native double getUserVoltage6V();
 
+  /**
+   * Gets the 6V rail current.
+   *
+   * @return the 6V rail current (amps)
+   * @see "HAL_GetUserCurrent6V"
+   */
   public static native double getUserCurrent6V();
 
+  /**
+   * Enables or disables the 6V rail.
+   *
+   * @param enabled whether the rail should be enabled
+   */
+  public static native void setUserEnabled6V(boolean enabled);
+
+  /**
+   * Gets the active state of the 6V rail.
+   *
+   * @return true if the rail is active, otherwise false
+   * @see "HAL_GetUserActive6V"
+   */
   public static native boolean getUserActive6V();
 
+  /**
+   * Gets the fault count for the 6V rail.
+   *
+   * @return the number of 6V fault counts
+   * @see "HAL_GetUserCurrentFaults6V"
+   */
   public static native int getUserCurrentFaults6V();
 
+  /**
+   * Gets the 5V rail voltage.
+   *
+   * @return the 5V rail voltage (volts)
+   * @see "HAL_GetUserVoltage5V"
+   */
   public static native double getUserVoltage5V();
 
+  /**
+   * Gets the 5V rail current.
+   *
+   * @return the 5V rail current (amps)
+   * @see "HAL_GetUserCurrent5V"
+   */
   public static native double getUserCurrent5V();
 
+  /**
+   * Enables or disables the 5V rail.
+   *
+   * @param enabled whether the rail should be enabled
+   */
+  public static native void setUserEnabled5V(boolean enabled);
+
+  /**
+   * Gets the active state of the 5V rail.
+   *
+   * @return true if the rail is active, otherwise false
+   * @see "HAL_GetUserActive5V"
+   */
   public static native boolean getUserActive5V();
 
+  /**
+   * Gets the fault count for the 5V rail.
+   *
+   * @return the number of 5V fault counts
+   * @see "HAL_GetUserCurrentFaults5V"
+   */
   public static native int getUserCurrentFaults5V();
 
+  /**
+   * Gets the 3V3 rail voltage.
+   *
+   * @return the 3V3 rail voltage (volts)
+   * @see "HAL_GetUserVoltage3V3"
+   */
   public static native double getUserVoltage3V3();
 
+  /**
+   * Gets the 3V3 rail current.
+   *
+   * @return the 3V3 rail current (amps)
+   * @see "HAL_GetUserCurrent3V3"
+   */
   public static native double getUserCurrent3V3();
 
+  /**
+   * Enables or disables the 3V3 rail.
+   *
+   * @param enabled whether the rail should be enabled
+   */
+  public static native void setUserEnabled3V3(boolean enabled);
+
+  /**
+   * Gets the active state of the 3V3 rail.
+   *
+   * @return true if the rail is active, otherwise false
+   * @see "HAL_GetUserActive3V3"
+   */
   public static native boolean getUserActive3V3();
 
+  /**
+   * Gets the fault count for the 3V3 rail.
+   *
+   * @return the number of 3V3 fault counts
+   * @see "HAL_GetUserCurrentFaults3V3"
+   */
   public static native int getUserCurrentFaults3V3();
 
+  /**
+   * Set the voltage the roboRIO will brownout and disable all outputs.
+   *
+   * <p>Note that this only does anything on the roboRIO 2. On the roboRIO it is a no-op.
+   *
+   * @param voltage The brownout voltage
+   * @see "HAL_SetBrownoutVoltage"
+   */
   public static native void setBrownoutVoltage(double voltage);
 
+  /**
+   * Get the current brownout voltage setting.
+   *
+   * @return The brownout voltage
+   * @see "HAL_GetBrownoutVoltage"
+   */
   public static native double getBrownoutVoltage();
+
+  /**
+   * Get the current CPU temperature in degrees Celsius.
+   *
+   * @return current CPU temperature in degrees Celsius
+   */
+  public static native double getCPUTemp();
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/REVPHFaults.java b/hal/src/main/java/edu/wpi/first/hal/REVPHFaults.java
index 3419810..23f0882 100644
--- a/hal/src/main/java/edu/wpi/first/hal/REVPHFaults.java
+++ b/hal/src/main/java/edu/wpi/first/hal/REVPHFaults.java
@@ -56,27 +56,27 @@
    * @param faults the fault bitfields
    */
   public REVPHFaults(int faults) {
-    Channel0Fault = (faults & 0x1) != 0;
-    Channel1Fault = (faults & 0x2) != 0;
-    Channel2Fault = (faults & 0x4) != 0;
-    Channel3Fault = (faults & 0x8) != 0;
-    Channel4Fault = (faults & 0x10) != 0;
-    Channel5Fault = (faults & 0x20) != 0;
-    Channel6Fault = (faults & 0x40) != 0;
-    Channel7Fault = (faults & 0x80) != 0;
-    Channel8Fault = (faults & 0x100) != 0;
-    Channel9Fault = (faults & 0x200) != 0;
-    Channel10Fault = (faults & 0x400) != 0;
-    Channel11Fault = (faults & 0x800) != 0;
-    Channel12Fault = (faults & 0x1000) != 0;
-    Channel13Fault = (faults & 0x2000) != 0;
-    Channel14Fault = (faults & 0x4000) != 0;
-    Channel15Fault = (faults & 0x8000) != 0;
-    CompressorOverCurrent = (faults & 0x8000) != 0;
-    CompressorOpen = (faults & 0x10000) != 0;
-    SolenoidOverCurrent = (faults & 0x20000) != 0;
-    Brownout = (faults & 0x40000) != 0;
-    CanWarning = (faults & 0x80000) != 0;
-    HardwareFault = (faults & 0x100000) != 0;
+    Channel0Fault = (faults & (1 << 0)) != 0;
+    Channel1Fault = (faults & (1 << 1)) != 0;
+    Channel2Fault = (faults & (1 << 2)) != 0;
+    Channel3Fault = (faults & (1 << 3)) != 0;
+    Channel4Fault = (faults & (1 << 4)) != 0;
+    Channel5Fault = (faults & (1 << 5)) != 0;
+    Channel6Fault = (faults & (1 << 6)) != 0;
+    Channel7Fault = (faults & (1 << 7)) != 0;
+    Channel8Fault = (faults & (1 << 8)) != 0;
+    Channel9Fault = (faults & (1 << 9)) != 0;
+    Channel10Fault = (faults & (1 << 10)) != 0;
+    Channel11Fault = (faults & (1 << 11)) != 0;
+    Channel12Fault = (faults & (1 << 12)) != 0;
+    Channel13Fault = (faults & (1 << 13)) != 0;
+    Channel14Fault = (faults & (1 << 14)) != 0;
+    Channel15Fault = (faults & (1 << 15)) != 0;
+    CompressorOverCurrent = (faults & (1 << 16)) != 0;
+    CompressorOpen = (faults & (1 << 17)) != 0;
+    SolenoidOverCurrent = (faults & (1 << 18)) != 0;
+    Brownout = (faults & (1 << 19)) != 0;
+    CanWarning = (faults & (1 << 20)) != 0;
+    HardwareFault = (faults & (1 << 21)) != 0;
   }
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/REVPHJNI.java b/hal/src/main/java/edu/wpi/first/hal/REVPHJNI.java
index 44c67a8..b1935b2 100644
--- a/hal/src/main/java/edu/wpi/first/hal/REVPHJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/REVPHJNI.java
@@ -4,20 +4,64 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * REV Pneumatic Hub (PH) HAL JNI functions.
+ *
+ * @see "REVPH.h"
+ */
 public class REVPHJNI extends JNIWrapper {
   public static final int COMPRESSOR_CONFIG_TYPE_DISABLED = 0;
   public static final int COMPRESSOR_CONFIG_TYPE_DIGITAL = 1;
   public static final int COMPRESSOR_CONFIG_TYPE_ANALOG = 2;
   public static final int COMPRESSOR_CONFIG_TYPE_HYBRID = 3;
 
+  /**
+   * Initializes a PH.
+   *
+   * @param module the CAN ID to initialize
+   * @return the created PH handle
+   * @see "HAL_InitializeREVP"
+   */
   public static native int initialize(int module);
 
+  /**
+   * Frees a PH handle.
+   *
+   * @param handle the PH handle
+   * @see "HAL_FreeREVPH"
+   */
   public static native void free(int handle);
 
+  /**
+   * Checks if a solenoid channel number is valid.
+   *
+   * @param channel the channel to check
+   * @return true if the channel is valid, otherwise false
+   * @see "HAL_CheckREVPHSolenoidChannel"
+   */
   public static native boolean checkSolenoidChannel(int channel);
 
+  /**
+   * Get whether compressor is turned on.
+   *
+   * @param handle the PH handle
+   * @return true if the compressor is turned on
+   * @see "HAL_GetREVPHCompressor"
+   */
   public static native boolean getCompressor(int handle);
 
+  /**
+   * Send compressor configuration to the PH.
+   *
+   * @param handle the PH handle
+   * @param minAnalogVoltage The compressor will turn on when the analog pressure sensor voltage
+   *     drops below this value
+   * @param maxAnalogVoltage The compressor will turn off when the analog pressure sensor reaches
+   *     this value.
+   * @param forceDisable Disable Compressor
+   * @param useDigital use the digital pressure switch
+   * @see "HAL_SetREVPHCompressorConfig"
+   */
   public static native void setCompressorConfig(
       int handle,
       double minAnalogVoltage,
@@ -25,51 +69,221 @@
       boolean forceDisable,
       boolean useDigital);
 
+  /**
+   * Disable Compressor.
+   *
+   * @param handle the PH handle
+   * @see "HAL_SetREVPHClosedLoopControlDisabled"
+   */
   public static native void setClosedLoopControlDisabled(int handle);
 
+  /**
+   * Enables the compressor in digital mode using the digital pressure switch. The compressor will
+   * turn on when the pressure switch indicates that the system is not full, and will turn off when
+   * the pressure switch indicates that the system is full.
+   *
+   * @param handle the PH handle
+   * @see "HAL_SetREVPHClosedLoopControlDigital"
+   */
   public static native void setClosedLoopControlDigital(int handle);
 
+  /**
+   * Enables the compressor in analog mode. This mode uses an analog pressure sensor connected to
+   * analog channel 0 to cycle the compressor. The compressor will turn on when the pressure drops
+   * below minAnalogVoltage and will turn off when the pressure reaches maxAnalogVoltage. This mode
+   * is only supported by the REV PH with the REV Analog Pressure Sensor connected to analog channel
+   * 0.
+   *
+   * @param handle the PH handle
+   * @param minAnalogVoltage The compressor will turn on when the analog pressure sensor voltage
+   *     drops below this value
+   * @param maxAnalogVoltage The compressor will turn off when the analog pressure sensor reaches
+   *     this value.
+   * @see "HAL_SetREVPHClosedLoopControlAnalog"
+   */
   public static native void setClosedLoopControlAnalog(
       int handle, double minAnalogVoltage, double maxAnalogVoltage);
 
+  /**
+   * Enables the compressor in hybrid mode. This mode uses both a digital pressure switch and an
+   * analog pressure sensor connected to analog channel 0 to cycle the compressor.
+   *
+   * <p>The compressor will turn on when \a both:
+   *
+   * <p>- The digital pressure switch indicates the system is not full AND - The analog pressure
+   * sensor indicates that the pressure in the system is below the specified minimum pressure.
+   *
+   * <p>The compressor will turn off when \a either:
+   *
+   * <p>- The digital pressure switch is disconnected or indicates that the system is full OR - The
+   * pressure detected by the analog sensor is greater than the specified maximum pressure.
+   *
+   * @param handle the PH handle
+   * @param minAnalogVoltage The compressor will turn on when the analog pressure sensor voltage
+   *     drops below this value and the pressure switch indicates that the system is not full.
+   * @param maxAnalogVoltage The compressor will turn off when the analog pressure sensor reaches
+   *     this value or the pressure switch is disconnected or indicates that the system is full.
+   * @see "HAL_SetREVPHClosedLoopControlHybrid"
+   */
   public static native void setClosedLoopControlHybrid(
       int handle, double minAnalogVoltage, double maxAnalogVoltage);
 
+  /**
+   * Get compressor configuration from the PH.
+   *
+   * @param handle the PH handle
+   * @return compressor configuration
+   * @see "HAL_GetREVPHCompressorConfig"
+   */
   public static native int getCompressorConfig(int handle);
 
+  /**
+   * Returns the state of the digital pressure switch.
+   *
+   * @param handle the PH handle
+   * @return True if pressure switch indicates that the system is full, otherwise false.
+   * @see "HAL_GetREVPHPressureSwitch"
+   */
   public static native boolean getPressureSwitch(int handle);
 
+  /**
+   * Returns the raw voltage of the specified analog input channel.
+   *
+   * @param handle the PH handle
+   * @param channel The analog input channel to read voltage from.
+   * @return The voltage of the specified analog input channel in volts.
+   * @see "HAL_GetREVPHAnalogVoltage"
+   */
   public static native double getAnalogVoltage(int handle, int channel);
 
+  /**
+   * Returns the current drawn by the compressor.
+   *
+   * @param handle the PH handle
+   * @return The current drawn by the compressor in amps.
+   * @see "HAL_GetREVPHCompressorCurrent"
+   */
   public static native double getCompressorCurrent(int handle);
 
+  /**
+   * Gets a bitmask of solenoid values.
+   *
+   * @param handle the PH handle
+   * @return solenoid values
+   * @see "HAL_GetREVPHSolenoids"
+   */
   public static native int getSolenoids(int handle);
 
+  /**
+   * Sets solenoids on a PH.
+   *
+   * @param handle the PH handle
+   * @param mask bitmask to set
+   * @param values solenoid values
+   * @see "HAL_SetREVPHSolenoids"
+   */
   public static native void setSolenoids(int handle, int mask, int values);
 
+  /**
+   * Fire a single solenoid shot for the specified duration.
+   *
+   * @param handle the PH handle
+   * @param index solenoid index
+   * @param durMs shot duration in ms
+   * @see "HAL_FireREVPHOneShot"
+   */
   public static native void fireOneShot(int handle, int index, int durMs);
 
+  /**
+   * Clears the sticky faults.
+   *
+   * @param handle the PH handle
+   * @see "HAL_ClearREVPHStickyFaults"
+   */
   public static native void clearStickyFaults(int handle);
 
+  /**
+   * Returns the current input voltage for the PH.
+   *
+   * @param handle the PH handle
+   * @return The input voltage in volts.
+   * @see "HAL_GetREVPHVoltage"
+   */
   public static native double getInputVoltage(int handle);
 
+  /**
+   * Returns the current voltage of the regulated 5v supply.
+   *
+   * @param handle the PH handle
+   * @return The current voltage of the 5v supply in volts.
+   * @see "HAL_GetREVPH5VVoltage"
+   */
   public static native double get5VVoltage(int handle);
 
+  /**
+   * Returns the total current drawn by all solenoids.
+   *
+   * @param handle the PH handle
+   * @return Total current drawn by all solenoids in amps.
+   * @see "HAL_GetREVPHSolenoidCurrent"
+   */
   public static native double getSolenoidCurrent(int handle);
 
+  /**
+   * Returns the current voltage of the solenoid power supply.
+   *
+   * @param handle the PH handle
+   * @return The current voltage of the solenoid power supply in volts.
+   * @see "HAL_GetREVPHSolenoidVoltage"
+   */
   public static native double getSolenoidVoltage(int handle);
 
+  /**
+   * Returns the sticky faults currently active on this device.
+   *
+   * @param handle the PH handle
+   * @return The sticky faults.
+   * @see "HAL_GetREVPHStickyFaults"
+   */
   public static native int getStickyFaultsNative(int handle);
 
+  /**
+   * Returns the sticky faults currently active on this device.
+   *
+   * @param handle the PH handle
+   * @return The sticky faults.
+   * @see "HAL_GetREVPHStickyFaults"
+   */
   public static REVPHStickyFaults getStickyFaults(int handle) {
     return new REVPHStickyFaults(getStickyFaultsNative(handle));
   }
 
+  /**
+   * Returns the faults currently active on the PH.
+   *
+   * @param handle the PH handle
+   * @return The faults.
+   * @see "HAL_GetREVPHFaults"
+   */
   public static native int getFaultsNative(int handle);
 
+  /**
+   * Returns the faults currently active on the PH.
+   *
+   * @param handle the PH handle
+   * @return The faults.
+   * @see "HAL_GetREVPHFaults"
+   */
   public static REVPHFaults getFaults(int handle) {
     return new REVPHFaults(getFaultsNative(handle));
   }
 
+  /**
+   * Returns the hardware and firmware versions of the PH.
+   *
+   * @param handle the PH handle
+   * @return The hardware and firmware versions.
+   * @see "HAL_GetREVPHVersion"
+   */
   public static native REVPHVersion getVersion(int handle);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/RelayJNI.java b/hal/src/main/java/edu/wpi/first/hal/RelayJNI.java
index eee2854..10a39b4 100644
--- a/hal/src/main/java/edu/wpi/first/hal/RelayJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/RelayJNI.java
@@ -4,14 +4,57 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Relay Output HAL JNI Functions.
+ *
+ * @see "hal/Relay.h"
+ */
 public class RelayJNI extends DIOJNI {
+  /**
+   * Initializes a relay.
+   *
+   * <p>Note this call will only initialize either the forward or reverse port of the relay. If you
+   * need both, you will need to initialize 2 relays.
+   *
+   * @param halPortHandle the port handle to initialize
+   * @param forward true for the forward port, false for the reverse port
+   * @return the created relay handle
+   * @see "HAL_InitializeRelayPort"
+   */
   public static native int initializeRelayPort(int halPortHandle, boolean forward);
 
+  /**
+   * Frees a relay port.
+   *
+   * @param relayPortHandle the relay handle
+   * @see "HAL_FreeRelayPort"
+   */
   public static native void freeRelayPort(int relayPortHandle);
 
+  /**
+   * Checks if a relay channel is valid.
+   *
+   * @param channel the channel to check
+   * @return true if the channel is valid, otherwise false
+   * @see "HAL_CheckRelayChannel"
+   */
   public static native boolean checkRelayChannel(int channel);
 
+  /**
+   * Sets the state of a relay output.
+   *
+   * @param relayPortHandle the relay handle
+   * @param on true for on, false for off
+   * @see "HAL_SetRelay"
+   */
   public static native void setRelay(int relayPortHandle, boolean on);
 
+  /**
+   * Gets the current state of the relay channel.
+   *
+   * @param relayPortHandle the relay handle
+   * @return true for on, false for off
+   * @see "HAL_GetRelay"
+   */
   public static native boolean getRelay(int relayPortHandle);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/SPIJNI.java b/hal/src/main/java/edu/wpi/first/hal/SPIJNI.java
index 053f192..82b9fed 100644
--- a/hal/src/main/java/edu/wpi/first/hal/SPIJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/SPIJNI.java
@@ -6,6 +6,11 @@
 
 import java.nio.ByteBuffer;
 
+/**
+ * SPI HAL JNI functions.
+ *
+ * @see "SPI.h"
+ */
 public class SPIJNI extends JNIWrapper {
   public static final int INVALID_PORT = -1;
   public static final int ONBOARD_CS0_PORT = 0;
@@ -19,40 +24,198 @@
   public static final int SPI_MODE2 = 2;
   public static final int SPI_MODE3 = 3;
 
+  /**
+   * Initializes the SPI port. Opens the port if necessary and saves the handle.
+   *
+   * <p>If opening the MXP port, also sets up the channel functions appropriately.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS3, 4 for MXP
+   * @see "HAL_InitializeSPI"
+   */
   public static native void spiInitialize(int port);
 
+  /**
+   * Performs an SPI send/receive transaction.
+   *
+   * <p>This is a lower-level interface to the spi hardware giving you more control over each
+   * transaction.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+   * @param dataToSend Buffer of data to send as part of the transaction.
+   * @param dataReceived Buffer to read data into.
+   * @param size Number of bytes to transfer. [0..7]
+   * @return Number of bytes transferred, -1 for error
+   * @see "HAL_TransactionSPI"
+   */
   public static native int spiTransaction(
       int port, ByteBuffer dataToSend, ByteBuffer dataReceived, byte size);
 
+  /**
+   * Performs an SPI send/receive transaction.
+   *
+   * <p>This is a lower-level interface to the spi hardware giving you more control over each
+   * transaction.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+   * @param dataToSend Buffer of data to send as part of the transaction.
+   * @param dataReceived Buffer to read data into.
+   * @param size Number of bytes to transfer. [0..7]
+   * @return Number of bytes transferred, -1 for error
+   * @see "HAL_TransactionSPI"
+   */
   public static native int spiTransactionB(
       int port, byte[] dataToSend, byte[] dataReceived, byte size);
 
+  /**
+   * Executes a write transaction with the device.
+   *
+   * <p>Writes to a device and wait until the transaction is complete.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+   * @param dataToSend The data to write to the register on the device.
+   * @param sendSize The number of bytes to be written
+   * @return The number of bytes written. -1 for an error
+   * @see "HAL_WriteSPI"
+   */
   public static native int spiWrite(int port, ByteBuffer dataToSend, byte sendSize);
 
+  /**
+   * Executes a write transaction with the device.
+   *
+   * <p>Writes to a device and wait until the transaction is complete.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+   * @param dataToSend The data to write to the register on the device.
+   * @param sendSize The number of bytes to be written
+   * @return The number of bytes written. -1 for an error
+   * @see "HAL_WriteSPI"
+   */
   public static native int spiWriteB(int port, byte[] dataToSend, byte sendSize);
 
+  /**
+   * Executes a read from the device.
+   *
+   * <p>This method does not write any data out to the device.
+   *
+   * <p>Most spi devices will require a register address to be written before they begin returning
+   * data.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+   * @param initiate initiates a transaction when true. Just reads when false.
+   * @param dataReceived A pointer to the array of bytes to store the data read from the device.
+   * @param size The number of bytes to read in the transaction. [1..7]
+   * @return Number of bytes read. -1 for error.
+   * @see "HAL_ReadSPI"
+   */
   public static native int spiRead(int port, boolean initiate, ByteBuffer dataReceived, byte size);
 
+  /**
+   * Executes a read from the device.
+   *
+   * <p>This method does not write any data out to the device.
+   *
+   * <p>Most spi devices will require a register address to be written before they begin returning
+   * data.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+   * @param initiate initiates a transaction when true. Just reads when false.
+   * @param dataReceived A pointer to the array of bytes to store the data read from the device.
+   * @param size The number of bytes to read in the transaction. [1..7]
+   * @return Number of bytes read. -1 for error.
+   * @see "HAL_ReadSPI"
+   */
   public static native int spiReadB(int port, boolean initiate, byte[] dataReceived, byte size);
 
+  /**
+   * Closes the SPI port.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+   * @see "HAL_CloseSPI"
+   */
   public static native void spiClose(int port);
 
+  /**
+   * Sets the clock speed for the SPI bus.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+   * @param speed The speed in Hz (500KHz-10MHz)
+   * @see "HAL_SetSPISpeed"
+   */
   public static native void spiSetSpeed(int port, int speed);
 
+  /**
+   * Sets the SPI Mode.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+   * @param mode The SPI mode to use
+   * @see "HAL_SetSPIMode"
+   */
   public static native void spiSetMode(int port, int mode);
 
+  /**
+   * Gets the SPI Mode.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+   * @return The SPI mode currently set
+   * @see "HAL_GetSPIMode"
+   */
   public static native int spiGetMode(int port);
 
+  /**
+   * Sets the CS Active high for a SPI port.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+   * @see "HAL_SetSPIChipSelectActiveHigh"
+   */
   public static native void spiSetChipSelectActiveHigh(int port);
 
+  /**
+   * Sets the CS Active low for a SPI port.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+   * @see "HAL_SetSPIChipSelectActiveLow"
+   */
   public static native void spiSetChipSelectActiveLow(int port);
 
+  /**
+   * Initializes the SPI automatic accumulator.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP.
+   * @param bufferSize The accumulator buffer size.
+   * @see "HAL_InitSPIAuto"
+   */
   public static native void spiInitAuto(int port, int bufferSize);
 
+  /**
+   * Frees an SPI automatic accumulator.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP.
+   * @see "HAL_FreeSPIAuto"
+   */
   public static native void spiFreeAuto(int port);
 
+  /**
+   * Sets the period for automatic SPI accumulation.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP.
+   * @param period The accumulation period (seconds).
+   * @see "HAL_StartSPIAutoRate"
+   */
   public static native void spiStartAutoRate(int port, double period);
 
+  /**
+   * Starts the auto SPI accumulator on a specific trigger.
+   *
+   * <p>Note that triggering on both rising and falling edges is a valid configuration.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP.
+   * @param digitalSourceHandle The trigger source to use (Either HAL_AnalogTriggerHandle or
+   *     HAL_DigitalHandle).
+   * @param analogTriggerType The analog trigger type, if the source is an analog trigger.
+   * @param triggerRising Trigger on the rising edge if true.
+   * @param triggerFalling Trigger on the falling edge if true.
+   * @see "HAL_StartSPIAutoTrigger"
+   */
   public static native void spiStartAutoTrigger(
       int port,
       int digitalSourceHandle,
@@ -60,20 +223,83 @@
       boolean triggerRising,
       boolean triggerFalling);
 
+  /**
+   * Stops an automatic SPI accumulation.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP.
+   * @see "HAL_StopSPIAuto"
+   */
   public static native void spiStopAuto(int port);
 
+  /**
+   * Sets the data to be transmitted to the device to initiate a read.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP.
+   * @param dataToSend Pointer to the data to send (Gets copied for continue use, so no need to keep
+   *     alive).
+   * @param zeroSize The number of zeros to send after the data.
+   * @see "HAL_SetSPIAutoTransmitData"
+   */
   public static native void spiSetAutoTransmitData(int port, byte[] dataToSend, int zeroSize);
 
+  /**
+   * Immediately forces an SPI read to happen.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP.
+   * @see "HAL_ForceSPIAutoRead"
+   */
   public static native void spiForceAutoRead(int port);
 
+  /**
+   * Reads data received by the SPI accumulator. 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 dataSize + zeroSize set in
+   * spiSetAutoTransmitData.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP.
+   * @param buffer The buffer to store the data into.
+   * @param numToRead The number of words to read.
+   * @param timeout The read timeout (in seconds).
+   * @return The number of words actually read.
+   * @see "HAL_ReadSPIAutoReceivedData"
+   */
   public static native int spiReadAutoReceivedData(
       int port, ByteBuffer buffer, int numToRead, double timeout);
 
+  /**
+   * Reads data received by the SPI accumulator. 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 dataSize + zeroSize set in
+   * spiSetAutoTransmitData.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP.
+   * @param buffer The buffer to store the data into.
+   * @param numToRead The number of words to read.
+   * @param timeout The read timeout (in seconds).
+   * @return The number of words actually read.
+   * @see "HAL_ReadSPIAutoReceivedData"
+   */
   public static native int spiReadAutoReceivedData(
       int port, int[] buffer, int numToRead, double timeout);
 
+  /**
+   * Gets the count of how many SPI accumulations have been missed.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP.
+   * @return The number of missed accumulations.
+   * @see "HAL_GetSPIAutoDroppedCount"
+   */
   public static native int spiGetAutoDroppedCount(int port);
 
+  /**
+   * Configure the Auto SPI Stall time between reads.
+   *
+   * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP.
+   * @param csToSclkTicks the number of ticks to wait before asserting the cs pin
+   * @param stallTicks the number of ticks to stall for
+   * @param pow2BytesPerRead the number of bytes to read before stalling
+   * @see "HAL_ConfigureSPIAutoStall"
+   */
   public static native void spiConfigureAutoStall(
       int port, int csToSclkTicks, int stallTicks, int pow2BytesPerRead);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/SerialPortJNI.java b/hal/src/main/java/edu/wpi/first/hal/SerialPortJNI.java
index ee9464e..e156f3a 100644
--- a/hal/src/main/java/edu/wpi/first/hal/SerialPortJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/SerialPortJNI.java
@@ -4,42 +4,205 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Serial Port JNI HAL functions.
+ *
+ * @see "SerialPort.h"
+ */
 public class SerialPortJNI extends JNIWrapper {
+  /**
+   * Initializes a serial port.
+   *
+   * <p>The channels are either the onboard RS232, the MXP UART, or 2 USB ports. The top port is
+   * USB1, the bottom port is USB2.
+   *
+   * @param port the serial port to initialize
+   * @return Serial Port Handle
+   * @see "HAL_InitializeSerialPort"
+   */
   public static native int serialInitializePort(byte port);
 
+  /**
+   * Initializes a serial port with a direct name.
+   *
+   * <p>This name is the /dev name for a specific port. Note these are not always consistent between
+   * roboRIO reboots.
+   *
+   * @param port the serial port to initialize
+   * @param portName the dev port name
+   * @return Serial Port Handle
+   * @see "HAL_InitializeSerialPortDirect"
+   */
   public static native int serialInitializePortDirect(byte port, String portName);
 
+  /**
+   * Sets the baud rate of a serial port.
+   *
+   * <p>Any value between 0 and 0xFFFFFFFF may be used. Default is 9600.
+   *
+   * @param handle the serial port handle
+   * @param baud the baud rate to set
+   * @see "HAL_SetSerialBaudRate"
+   */
   public static native void serialSetBaudRate(int handle, int baud);
 
+  /**
+   * Sets the number of data bits on a serial port.
+   *
+   * <p>Defaults to 8.
+   *
+   * @param handle the serial port handle
+   * @param bits the number of data bits (5-8)
+   * @see "HAL_SetSerialDataBits"
+   */
   public static native void serialSetDataBits(int handle, byte bits);
 
+  /**
+   * Sets the number of parity bits on a serial port.
+   *
+   * <p>Valid values are: 0: None (default) 1: Odd 2: Even 3: Mark - Means exists and always 1 4:
+   * Space - Means exists and always 0
+   *
+   * @param handle the serial port handle
+   * @param parity the parity bit mode (see remarks for valid values)
+   * @see "HAL_SetSerialParity"
+   */
   public static native void serialSetParity(int handle, byte parity);
 
+  /**
+   * Sets the number of stop bits on a serial port.
+   *
+   * <p>Valid values are: 10: One stop bit (default) 15: One and a half stop bits 20: Two stop bits
+   *
+   * @param handle the serial port handle
+   * @param stopBits the stop bit value (see remarks for valid values)
+   * @see "HAL_SetSerialStopBits"
+   */
   public static native void serialSetStopBits(int handle, byte stopBits);
 
+  /**
+   * Sets the write mode on a serial port.
+   *
+   * <p>Valid values are: 1: Flush on access 2: Flush when full (default)
+   *
+   * @param handle the serial port handle
+   * @param mode the mode to set (see remarks for valid values)
+   * @see "HAL_SetSerialWriteMode"
+   */
   public static native void serialSetWriteMode(int handle, byte mode);
 
+  /**
+   * Sets the flow control mode of a serial port.
+   *
+   * <p>Valid values are: 0: None (default) 1: XON-XOFF 2: RTS-CTS 3: DTR-DSR
+   *
+   * @param handle the serial port handle
+   * @param flow the mode to set (see remarks for valid values)
+   * @see "HAL_SetSerialFlowControl"
+   */
   public static native void serialSetFlowControl(int handle, byte flow);
 
+  /**
+   * Sets the minimum serial read timeout of a port.
+   *
+   * @param handle the serial port handle
+   * @param timeout the timeout in milliseconds
+   * @see "HAL_SetSerialTimeout"
+   */
   public static native void serialSetTimeout(int handle, double timeout);
 
+  /**
+   * Sets the termination character that terminates a read.
+   *
+   * <p>By default this is disabled.
+   *
+   * @param handle the serial port handle
+   * @param terminator the termination character to set
+   * @see "HAL_EnableSerialTermination"
+   */
   public static native void serialEnableTermination(int handle, char terminator);
 
+  /**
+   * Disables a termination character for reads.
+   *
+   * @param handle the serial port handle
+   * @see "HAL_DisableSerialTermination"
+   */
   public static native void serialDisableTermination(int handle);
 
+  /**
+   * Sets the size of the read buffer.
+   *
+   * @param handle the serial port handle
+   * @param size the read buffer size
+   * @see "HAL_SetSerialReadBufferSize"
+   */
   public static native void serialSetReadBufferSize(int handle, int size);
 
+  /**
+   * Sets the size of the write buffer.
+   *
+   * @param handle the serial port handle
+   * @param size the write buffer size
+   * @see "HAL_SetSerialWriteBufferSize"
+   */
   public static native void serialSetWriteBufferSize(int handle, int size);
 
+  /**
+   * Gets the number of bytes currently in the read buffer.
+   *
+   * @param handle the serial port handle
+   * @return the number of bytes in the read buffer
+   * @see "HAL_GetSerialBytesReceived"
+   */
   public static native int serialGetBytesReceived(int handle);
 
+  /**
+   * Reads data from the serial port.
+   *
+   * <p>Will wait for either timeout (if set), the termination char (if set), or the count to be
+   * full. Whichever one comes first.
+   *
+   * @param handle the serial port handle
+   * @param buffer the buffer in which to store bytes read
+   * @param count the number of bytes maximum to read
+   * @return the number of bytes actually read
+   * @see "HAL_ReadSerial"
+   */
   public static native int serialRead(int handle, byte[] buffer, int count);
 
+  /**
+   * Writes data to the serial port.
+   *
+   * @param handle the serial port handle
+   * @param buffer the buffer to write
+   * @param count the number of bytes to write from the buffer
+   * @return the number of bytes actually written
+   * @see "HAL_WriteSerial"
+   */
   public static native int serialWrite(int handle, byte[] buffer, int count);
 
+  /**
+   * Flushes the serial write buffer out to the port.
+   *
+   * @param handle the serial port handle
+   * @see "HAL_FlushSerial"
+   */
   public static native void serialFlush(int handle);
 
+  /**
+   * Clears the receive buffer of the serial port.
+   *
+   * @param handle the serial port handle
+   * @see "HAL_ClearSerial"
+   */
   public static native void serialClear(int handle);
 
+  /**
+   * Closes a serial port.
+   *
+   * @param handle the serial port handle to close
+   * @see "HAL_CloseSerial"
+   */
   public static native void serialClose(int handle);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/SimDevice.java b/hal/src/main/java/edu/wpi/first/hal/SimDevice.java
index db3a587..21ac69a 100644
--- a/hal/src/main/java/edu/wpi/first/hal/SimDevice.java
+++ b/hal/src/main/java/edu/wpi/first/hal/SimDevice.java
@@ -32,7 +32,7 @@
    * Creates a simulated device.
    *
    * <p>The device name must be unique. Returns null if the device name already exists. If multiple
-   * instances of the same device are desired, recommend appending the instance/unique identifer in
+   * instances of the same device are desired, recommend appending the instance/unique identifier in
    * brackets to the base name, e.g. "device[1]".
    *
    * <p>null is returned if not in simulation.
@@ -107,6 +107,15 @@
   }
 
   /**
+   * Get the name of the simulated device.
+   *
+   * @return the name
+   */
+  public String getName() {
+    return SimDeviceJNI.getSimDeviceName(m_handle);
+  }
+
+  /**
    * Creates a value on the simulated device.
    *
    * <p>Returns null if not in simulation.
diff --git a/hal/src/main/java/edu/wpi/first/hal/SimDeviceJNI.java b/hal/src/main/java/edu/wpi/first/hal/SimDeviceJNI.java
index 8723cd3..4352a2d 100644
--- a/hal/src/main/java/edu/wpi/first/hal/SimDeviceJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/SimDeviceJNI.java
@@ -13,7 +13,7 @@
    * Creates a simulated device.
    *
    * <p>The device name must be unique. 0 is returned if the device name already exists. If multiple
-   * instances of the same device are desired, recommend appending the instance/unique identifer in
+   * instances of the same device are desired, recommend appending the instance/unique identifier in
    * brackets to the base name, e.g. "device[1]".
    *
    * <p>0 is returned if not in simulation.
@@ -33,6 +33,14 @@
    */
   public static native void freeSimDevice(int handle);
 
+  /**
+   * Get the name of a simulated device.
+   *
+   * @param handle simulated device handle
+   * @return name of the simulated device
+   */
+  public static native String getSimDeviceName(int handle);
+
   private static native int createSimValueNative(
       int device, String name, int direction, int type, long value1, double value2);
 
diff --git a/hal/src/main/java/edu/wpi/first/hal/ThreadsJNI.java b/hal/src/main/java/edu/wpi/first/hal/ThreadsJNI.java
index c854e20..2ccc808 100644
--- a/hal/src/main/java/edu/wpi/first/hal/ThreadsJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/ThreadsJNI.java
@@ -4,10 +4,37 @@
 
 package edu.wpi.first.hal;
 
+/**
+ * Threads HAL JNI Functions.
+ *
+ * @see "Threads.h"
+ */
 public class ThreadsJNI extends JNIWrapper {
+  /**
+   * Gets the thread priority for the current thread.
+   *
+   * @return The current thread priority. For real-time, this is 1-99 with 99 being highest. For
+   *     non-real-time, this is 0. See "man 7 sched" for details.
+   * @see "HAL_GetCurrentThreadPriority"
+   */
   public static native int getCurrentThreadPriority();
 
+  /**
+   * Gets the real-time status for the current thread.
+   *
+   * @return Set to true if thread is real-time, otherwise false.
+   * @see "HAL_GetCurrentThreadPriority"
+   */
   public static native boolean getCurrentThreadIsRealTime();
 
+  /**
+   * Sets the thread priority for the current thread.
+   *
+   * @param realTime Set to true to set a real-time priority, false for standard priority.
+   * @param priority Priority to set the thread to. For real-time, this is 1-99 with 99 being
+   *     highest. For non-real-time, this is forced to 0. See "man 7 sched" for more details.
+   * @return True on success.
+   * @see "HAL_SetCurrentThreadPriority"
+   */
   public static native boolean setCurrentThreadPriority(boolean realTime, int priority);
 }
diff --git a/hal/src/main/java/edu/wpi/first/hal/simulation/EncoderDataJNI.java b/hal/src/main/java/edu/wpi/first/hal/simulation/EncoderDataJNI.java
index fc9d2e5..e48607a 100644
--- a/hal/src/main/java/edu/wpi/first/hal/simulation/EncoderDataJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/simulation/EncoderDataJNI.java
@@ -79,6 +79,15 @@
 
   public static native void setSamplesToAverage(int index, int samplesToAverage);
 
+  public static native int registerDistancePerPulseCallback(
+      int index, NotifyCallback callback, boolean initialNotify);
+
+  public static native void cancelDistancePerPulseCallback(int index, int uid);
+
+  public static native double getDistancePerPulse(int index);
+
+  public static native void setDistancePerPulse(int index, double distancePerPulse);
+
   public static native void setDistance(int index, double distance);
 
   public static native double getDistance(int index);
diff --git a/hal/src/main/java/edu/wpi/first/hal/simulation/PWMDataJNI.java b/hal/src/main/java/edu/wpi/first/hal/simulation/PWMDataJNI.java
index bf75398..d66256b 100644
--- a/hal/src/main/java/edu/wpi/first/hal/simulation/PWMDataJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/simulation/PWMDataJNI.java
@@ -16,14 +16,14 @@
 
   public static native void setInitialized(int index, boolean initialized);
 
-  public static native int registerRawValueCallback(
+  public static native int registerPulseMicrosecondCallback(
       int index, NotifyCallback callback, boolean initialNotify);
 
-  public static native void cancelRawValueCallback(int index, int uid);
+  public static native void cancelPulseMicrosecondCallback(int index, int uid);
 
-  public static native int getRawValue(int index);
+  public static native int getPulseMicrosecond(int index);
 
-  public static native void setRawValue(int index, int rawValue);
+  public static native void setPulseMicrosecond(int index, int microsecondPulseTime);
 
   public static native int registerSpeedCallback(
       int index, NotifyCallback callback, boolean initialNotify);
diff --git a/hal/src/main/java/edu/wpi/first/hal/simulation/RoboRioDataJNI.java b/hal/src/main/java/edu/wpi/first/hal/simulation/RoboRioDataJNI.java
index ef06067..7f51331 100644
--- a/hal/src/main/java/edu/wpi/first/hal/simulation/RoboRioDataJNI.java
+++ b/hal/src/main/java/edu/wpi/first/hal/simulation/RoboRioDataJNI.java
@@ -151,6 +151,23 @@
 
   public static native void setBrownoutVoltage(double brownoutVoltage);
 
+  public static native int registerCPUTempCallback(NotifyCallback callback, boolean initialNotify);
+
+  public static native void cancelCPUTempCallback(int uid);
+
+  public static native double getCPUTemp();
+
+  public static native void setCPUTemp(double cpuTemp);
+
+  public static native int registerTeamNumberCallback(
+      NotifyCallback callback, boolean initialNotify);
+
+  public static native void cancelTeamNumberCallback(int uid);
+
+  public static native int getTeamNumber();
+
+  public static native void setTeamNumber(int teamNumber);
+
   public static native String getSerialNumber();
 
   public static native void setSerialNumber(String serialNumber);
diff --git a/hal/src/main/native/athena/AddressableLED.cpp b/hal/src/main/native/athena/AddressableLED.cpp
index 5e55c93..57f37cb 100644
--- a/hal/src/main/native/athena/AddressableLED.cpp
+++ b/hal/src/main/native/athena/AddressableLED.cpp
@@ -206,10 +206,10 @@
 }
 
 void HAL_SetAddressableLEDBitTiming(HAL_AddressableLEDHandle handle,
-                                    int32_t lowTime0NanoSeconds,
                                     int32_t highTime0NanoSeconds,
-                                    int32_t lowTime1NanoSeconds,
+                                    int32_t lowTime0NanoSeconds,
                                     int32_t highTime1NanoSeconds,
+                                    int32_t lowTime1NanoSeconds,
                                     int32_t* status) {
   auto led = addressableLEDHandles->Get(handle);
   if (!led) {
@@ -217,10 +217,10 @@
     return;
   }
 
-  led->led->writeLowBitTickTiming(1, highTime0NanoSeconds / 25, status);
-  led->led->writeLowBitTickTiming(0, lowTime0NanoSeconds / 25, status);
-  led->led->writeHighBitTickTiming(1, highTime1NanoSeconds / 25, status);
-  led->led->writeHighBitTickTiming(0, lowTime1NanoSeconds / 25, status);
+  led->led->writeLowBitTickTiming(0, highTime0NanoSeconds / 25, status);
+  led->led->writeLowBitTickTiming(1, lowTime0NanoSeconds / 25, status);
+  led->led->writeHighBitTickTiming(0, highTime1NanoSeconds / 25, status);
+  led->led->writeHighBitTickTiming(1, lowTime1NanoSeconds / 25, status);
 }
 
 void HAL_SetAddressableLEDSyncTime(HAL_AddressableLEDHandle handle,
diff --git a/hal/src/main/native/athena/AnalogGyro.cpp b/hal/src/main/native/athena/AnalogGyro.cpp
index 19f26dd..1751ac0 100644
--- a/hal/src/main/native/athena/AnalogGyro.cpp
+++ b/hal/src/main/native/athena/AnalogGyro.cpp
@@ -4,6 +4,7 @@
 
 #include "hal/AnalogGyro.h"
 
+#include <cmath>
 #include <string>
 #include <thread>
 
@@ -204,8 +205,8 @@
     return;
   }
 
-  gyro->center = static_cast<int32_t>(
-      static_cast<double>(value) / static_cast<double>(count) + 0.5);
+  gyro->center =
+      std::round(static_cast<double>(value) / static_cast<double>(count));
 
   gyro->offset = static_cast<double>(value) / static_cast<double>(count) -
                  static_cast<double>(gyro->center);
diff --git a/hal/src/main/native/athena/AnalogInternal.h b/hal/src/main/native/athena/AnalogInternal.h
index 431c624..eb8116b 100644
--- a/hal/src/main/native/athena/AnalogInternal.h
+++ b/hal/src/main/native/athena/AnalogInternal.h
@@ -69,7 +69,7 @@
  * number of active channels and the sample rate.
  *
  * When the number of channels changes, use the new value.  Otherwise,
- * return the curent value.
+ * return the current value.
  *
  * @return Value to write to the active channels field.
  */
diff --git a/hal/src/main/native/athena/CANAPI.cpp b/hal/src/main/native/athena/CANAPI.cpp
index a3e4904..70f09e0 100644
--- a/hal/src/main/native/athena/CANAPI.cpp
+++ b/hal/src/main/native/athena/CANAPI.cpp
@@ -35,15 +35,6 @@
 static UnlimitedHandleResource<HAL_CANHandle, CANStorage, HAL_HandleEnum::CAN>*
     canHandles;
 
-static uint32_t GetPacketBaseTime() {
-  timespec t;
-  clock_gettime(CLOCK_MONOTONIC, &t);
-
-  // Convert t to milliseconds
-  uint64_t ms = t.tv_sec * 1000ull + t.tv_nsec / 1000000ull;
-  return ms & 0xFFFFFFFF;
-}
-
 namespace hal::init {
 void InitializeCANAPI() {
   static UnlimitedHandleResource<HAL_CANHandle, CANStorage, HAL_HandleEnum::CAN>
@@ -63,6 +54,15 @@
 
 extern "C" {
 
+uint32_t HAL_GetCANPacketBaseTime(void) {
+  timespec t;
+  clock_gettime(CLOCK_MONOTONIC, &t);
+
+  // Convert t to milliseconds
+  uint64_t ms = t.tv_sec * 1000ull + t.tv_nsec / 1000000ull;
+  return ms & 0xFFFFFFFF;
+}
+
 HAL_CANHandle HAL_InitializeCAN(HAL_CANManufacturer manufacturer,
                                 int32_t deviceId, HAL_CANDeviceType deviceType,
                                 int32_t* status) {
@@ -267,7 +267,7 @@
     auto i = can->receives.find(messageId);
     if (i != can->receives.end()) {
       // Found, check if new enough
-      uint32_t now = GetPacketBaseTime();
+      uint32_t now = HAL_GetCANPacketBaseTime();
       if (now - i->second.lastTimeStamp > static_cast<uint32_t>(timeoutMs)) {
         // Timeout, return bad status
         *status = HAL_CAN_TIMEOUT;
diff --git a/hal/src/main/native/athena/DIO.cpp b/hal/src/main/native/athena/DIO.cpp
index e6308fb..d75f32b 100644
--- a/hal/src/main/native/athena/DIO.cpp
+++ b/hal/src/main/native/athena/DIO.cpp
@@ -200,8 +200,7 @@
   if (*status != 0) {
     return;
   }
-  uint16_t pwmPeriodPower =
-      std::lround(std::log(1.0 / (16 * 1.0E-6 * rate)) / std::log(2.0));
+  uint16_t pwmPeriodPower = std::lround(std::log2(1.0 / (16 * 1.0E-6 * rate)));
   digitalSystem->writePWMPeriodPower(pwmPeriodPower, status);
 }
 
@@ -231,12 +230,13 @@
       // frequencies.
       rawDutyCycle = rawDutyCycle / std::pow(2.0, 4 - pwmPeriodPower);
     }
-    if (id < 4)
+    if (id < 4) {
       digitalSystem->writePWMDutyCycleA(id, static_cast<uint8_t>(rawDutyCycle),
                                         status);
-    else
+    } else {
       digitalSystem->writePWMDutyCycleB(
           id - 4, static_cast<uint8_t>(rawDutyCycle), status);
+    }
   }
 }
 
@@ -255,12 +255,13 @@
   }
   {
     std::scoped_lock lock(digitalPwmMutex);
-    if (id < 4)
+    if (id < 4) {
       digitalSystem->writePWMDutyCycleA(id, static_cast<uint8_t>(rawDutyCycle),
                                         status);
-    else
+    } else {
       digitalSystem->writePWMDutyCycleB(
           id - 4, static_cast<uint8_t>(rawDutyCycle), status);
+    }
   }
 }
 
diff --git a/hal/src/main/native/athena/DigitalInternal.cpp b/hal/src/main/native/athena/DigitalInternal.cpp
index b9339ee..fb0cf98 100644
--- a/hal/src/main/native/athena/DigitalInternal.cpp
+++ b/hal/src/main/native/athena/DigitalInternal.cpp
@@ -112,9 +112,7 @@
 
   pwmSystem->writeConfig_Period(std::lround(kDefaultPwmPeriod / loopTime),
                                 status);
-  uint16_t minHigh = std::lround(
-      (kDefaultPwmCenter - kDefaultPwmStepsDown * loopTime) / loopTime);
-  pwmSystem->writeConfig_MinHigh(minHigh, status);
+  pwmSystem->writeConfig_MinHigh(0, status);
   // Ensure that PWM output values are set to OFF
   for (uint8_t pwmIndex = 0; pwmIndex < kNumPWMChannels; pwmIndex++) {
     // Copy of SetPWM
diff --git a/hal/src/main/native/athena/DigitalInternal.h b/hal/src/main/native/athena/DigitalInternal.h
index 685987a..5b73a39 100644
--- a/hal/src/main/native/athena/DigitalInternal.h
+++ b/hal/src/main/native/athena/DigitalInternal.h
@@ -47,15 +47,8 @@
  * devices.
  */
 constexpr double kDefaultPwmPeriod = 5.05;
-/**
- * kDefaultPwmCenter is the PWM range center in ms
- */
-constexpr double kDefaultPwmCenter = 1.5;
-/**
- * kDefaultPWMStepsDown is the number of PWM steps below the centerpoint
- */
-constexpr int32_t kDefaultPwmStepsDown = 1000;
 constexpr int32_t kPwmDisabled = 0;
+constexpr int32_t kPwmAlwaysHigh = 0xFFFF;
 
 extern std::unique_ptr<tDIO> digitalSystem;
 extern std::unique_ptr<tRelay> relaySystem;
diff --git a/hal/src/main/native/athena/FPGACalls.h b/hal/src/main/native/athena/FPGACalls.h
index 46e8ac4..3ef9004 100644
--- a/hal/src/main/native/athena/FPGACalls.h
+++ b/hal/src/main/native/athena/FPGACalls.h
@@ -8,7 +8,8 @@
 
 namespace hal {
 namespace init {
-[[nodiscard]] int InitializeFPGA();
+[[nodiscard]]
+int InitializeFPGA();
 }  // namespace init
 
 using HAL_NiFpga_ReserveIrqContextFunc =
diff --git a/hal/src/main/native/athena/FPGAEncoder.h b/hal/src/main/native/athena/FPGAEncoder.h
index b401ccd..a819d96 100644
--- a/hal/src/main/native/athena/FPGAEncoder.h
+++ b/hal/src/main/native/athena/FPGAEncoder.h
@@ -37,7 +37,7 @@
 /**
  * Returns the period of the most recent pulse.
  * Returns the period of the most recent Encoder pulse in seconds.
- * This method compenstates for the decoding type.
+ * This method compensates for the decoding type.
  *
  * @deprecated Use GetRate() in favor of this method.  This returns unscaled
  * periods and GetRate() scales using value from SetDistancePerPulse().
diff --git a/hal/src/main/native/athena/FRCDriverStation.cpp b/hal/src/main/native/athena/FRCDriverStation.cpp
index e8db9a5..12739c8 100644
--- a/hal/src/main/native/athena/FRCDriverStation.cpp
+++ b/hal/src/main/native/athena/FRCDriverStation.cpp
@@ -43,6 +43,7 @@
   HAL_JoystickButtons buttons[HAL_kMaxJoysticks];
   HAL_AllianceStationID allianceStation;
   float matchTime;
+  HAL_ControlWord controlWord;
 };
 static_assert(std::is_standard_layout_v<JoystickDataCache>);
 // static_assert(std::is_trivial_v<JoystickDataCache>);
@@ -101,9 +102,14 @@
     HAL_GetJoystickPOVsInternal(i, &povs[i]);
     HAL_GetJoystickButtonsInternal(i, &buttons[i]);
   }
-  FRC_NetworkCommunication_getAllianceStation(
-      reinterpret_cast<AllianceStationID_t*>(&allianceStation));
+  AllianceStationID_t alliance = kAllianceStationID_red1;
+  FRC_NetworkCommunication_getAllianceStation(&alliance);
+  int allianceInt = alliance;
+  allianceInt += 1;
+  allianceStation = static_cast<HAL_AllianceStationID>(allianceInt);
   FRC_NetworkCommunication_getMatchTime(&matchTime);
+  FRC_NetworkCommunication_getControlWord(
+      reinterpret_cast<ControlWord_t*>(&controlWord));
 }
 
 #define CHECK_JOYSTICK_NUMBER(stickNum)                  \
@@ -114,7 +120,7 @@
 static JoystickDataCache caches[3];
 static JoystickDataCache* currentRead = &caches[0];
 static JoystickDataCache* currentReadLocal = &caches[0];
-static std::atomic<JoystickDataCache*> currentCache{&caches[1]};
+static std::atomic<JoystickDataCache*> currentCache{nullptr};
 static JoystickDataCache* lastGiven = &caches[1];
 static JoystickDataCache* cacheToUpdate = &caches[2];
 
@@ -508,17 +514,27 @@
   }
 }
 
-void HAL_RefreshDSData(void) {
+HAL_Bool HAL_RefreshDSData(void) {
   HAL_ControlWord controlWord;
   std::memset(&controlWord, 0, sizeof(controlWord));
   FRC_NetworkCommunication_getControlWord(
       reinterpret_cast<ControlWord_t*>(&controlWord));
-  std::scoped_lock lock{cacheMutex};
-  JoystickDataCache* prev = currentCache.exchange(nullptr);
-  if (prev != nullptr) {
-    currentRead = prev;
+  JoystickDataCache* prev;
+  {
+    std::scoped_lock lock{cacheMutex};
+    prev = currentCache.exchange(nullptr);
+    if (prev != nullptr) {
+      currentRead = prev;
+    }
+    // If newest state shows we have a DS attached, just use the
+    // control word out of the cache, As it will be the one in sync
+    // with the data. Otherwise use the state that shows disconnected.
+    if (controlWord.dsAttached) {
+      newestControlWord = currentRead->controlWord;
+    } else {
+      newestControlWord = controlWord;
+    }
   }
-  newestControlWord = controlWord;
 
   uint32_t mask = tcpMask.exchange(0);
   if (mask != 0) {
@@ -526,6 +542,7 @@
     std::scoped_lock tcpLock(tcpCacheMutex);
     tcpCache.CloneTo(&tcpCurrent);
   }
+  return prev != nullptr;
 }
 
 void HAL_ProvideNewDataEventHandle(WPI_EventHandle handle) {
@@ -551,4 +568,13 @@
   setNewDataOccurRef(refNumber);
   FRC_NetworkCommunication_setNewTcpDataOccurRef(tcpRefNumber);
 }
+
+void WaitForInitialPacket() {
+  wpi::Event waitForInitEvent;
+  driverStation->newDataEvents.Add(waitForInitEvent.GetHandle());
+  bool timed_out = false;
+  wpi::WaitForObject(waitForInitEvent.GetHandle(), 0.1, &timed_out);
+  // Don't care what the result is, just want to give it a chance.
+  driverStation->newDataEvents.Remove(waitForInitEvent.GetHandle());
+}
 }  // namespace hal
diff --git a/hal/src/main/native/athena/HAL.cpp b/hal/src/main/native/athena/HAL.cpp
index 3a8cefd..d00bf9f 100644
--- a/hal/src/main/native/athena/HAL.cpp
+++ b/hal/src/main/native/athena/HAL.cpp
@@ -33,6 +33,7 @@
 #include "hal/Errors.h"
 #include "hal/Notifier.h"
 #include "hal/handles/HandlesInternal.h"
+#include "hal/roborio/HMB.h"
 #include "hal/roborio/InterruptManager.h"
 #include "visa/visa.h"
 
@@ -46,10 +47,16 @@
 static size_t roboRioCommentsStringSize;
 static bool roboRioCommentsStringInitialized;
 
+static int32_t teamNumber = -1;
+
+static const volatile HAL_HMBData* hmbBuffer;
+#define HAL_HMB_TIMESTAMP_OFFSET 5
+
 using namespace hal;
 
 namespace hal {
 void InitializeDriverStation();
+void WaitForInitialPacket();
 namespace init {
 void InitializeHAL() {
   InitializeCTREPCM();
@@ -252,12 +259,10 @@
   }
 }
 
+static HAL_RuntimeType runtimeType = HAL_Runtime_RoboRIO;
+
 HAL_RuntimeType HAL_GetRuntimeType(void) {
-  nLoadOut::tTargetClass targetClass = nLoadOut::getTargetClass();
-  if (targetClass == nLoadOut::kTargetClass_RoboRIO2) {
-    return HAL_Runtime_RoboRIO2;
-  }
-  return HAL_Runtime_RoboRIO;
+  return runtimeType;
 }
 
 int32_t HAL_GetFPGAVersion(int32_t* status) {
@@ -317,11 +322,8 @@
       return;
     }
     start += searchString.size();
-    size_t end = fileContents.find("\"", start);
-    if (end == std::string_view::npos) {
-      end = fileContents.size();
-    }
-    std::string_view escapedComments = wpi::slice(fileContents, start, end);
+    std::string_view escapedComments =
+        wpi::slice(fileContents, start, fileContents.size());
     wpi::SmallString<64> buf;
     auto [unescapedComments, rem] = wpi::UnescapeCString(escapedComments, buf);
     unescapedComments.copy(roboRioCommentsString,
@@ -353,27 +355,61 @@
   return toCopy;
 }
 
+void InitializeTeamNumber(void) {
+  char hostnameBuf[25];
+  auto status = gethostname(hostnameBuf, sizeof(hostnameBuf));
+  if (status != 0) {
+    teamNumber = 0;
+    return;
+  }
+
+  std::string_view hostname{hostnameBuf, sizeof(hostnameBuf)};
+
+  // hostname is frc-{TEAM}-roborio
+  // Split string around '-' (max of 2 splits), take the second element of the
+  // resulting array.
+  wpi::SmallVector<std::string_view> elements;
+  wpi::split(hostname, elements, "-", 2);
+  if (elements.size() < 3) {
+    teamNumber = 0;
+    return;
+  }
+
+  teamNumber = wpi::parse_integer<int32_t>(elements[1], 10).value_or(0);
+}
+
+int32_t HAL_GetTeamNumber(void) {
+  if (teamNumber == -1) {
+    InitializeTeamNumber();
+  }
+  return teamNumber;
+}
+
 uint64_t HAL_GetFPGATime(int32_t* status) {
   hal::init::CheckInit();
-  if (!global) {
+  if (!hmbBuffer) {
     *status = NiFpga_Status_ResourceNotInitialized;
     return 0;
   }
-  *status = 0;
-  uint64_t upper1 = global->readLocalTimeUpper(status);
-  uint32_t lower = global->readLocalTime(status);
-  uint64_t upper2 = global->readLocalTimeUpper(status);
-  if (*status != 0) {
-    return 0;
-  }
+
+  asm("dmb");
+  uint64_t upper1 = hmbBuffer->Timestamp.Upper;
+  asm("dmb");
+  uint32_t lower = hmbBuffer->Timestamp.Lower;
+  asm("dmb");
+  uint64_t upper2 = hmbBuffer->Timestamp.Upper;
+
   if (upper1 != upper2) {
     // Rolled over between the lower call, reread lower
-    lower = global->readLocalTime(status);
-    if (*status != 0) {
-      return 0;
-    }
+    asm("dmb");
+    lower = hmbBuffer->Timestamp.Lower;
   }
-  return (upper2 << 32) + lower;
+  // 5 is added here because the time to write from the FPGA
+  // to the HMB buffer is longer then the time to read
+  // from the time register. This would cause register based
+  // timestamps to be ahead of HMB timestamps, which could
+  // be very bad.
+  return (upper2 << 32) + lower + HAL_HMB_TIMESTAMP_OFFSET;
 }
 
 uint64_t HAL_ExpandFPGATime(uint32_t unexpandedLower, int32_t* status) {
@@ -427,6 +463,21 @@
   return !(watchdog->readStatus_PowerAlive(status));
 }
 
+HAL_Bool HAL_GetRSLState(int32_t* status) {
+  hal::init::CheckInit();
+  if (!global) {
+    *status = NiFpga_Status_ResourceNotInitialized;
+    return false;
+  }
+  return global->readLEDs_RSL(status);
+}
+
+HAL_Bool HAL_GetSystemTimeValid(int32_t* status) {
+  uint8_t timeWasSet = 0;
+  *status = FRC_NetworkCommunication_getTimeWasSet(&timeWasSet);
+  return timeWasSet != 0;
+}
+
 static bool killExistingProgram(int timeout, int mode) {
   // Kill any previous robot programs
   std::fstream fs;
@@ -511,10 +562,18 @@
     setNewDataSem(nullptr);
   });
 
-  nFPGA::nRoboRIO_FPGANamespace::g_currentTargetClass =
-      nLoadOut::getTargetClass();
+  // Setup WPI_Now to use FPGA timestamp
+  // this also sets nFPGA::nRoboRIO_FPGANamespace::g_currentTargetClass
+  wpi::impl::SetupNowRio();
 
   int32_t status = 0;
+
+  HAL_InitializeHMB(&status);
+  if (status != 0) {
+    return false;
+  }
+  hmbBuffer = HAL_GetHMBBuffer();
+
   global.reset(tGlobal::create(&status));
   watchdog.reset(tSysWatchdog::create(&status));
 
@@ -522,6 +581,13 @@
     return false;
   }
 
+  nLoadOut::tTargetClass targetClass = nLoadOut::getTargetClass();
+  if (targetClass == nLoadOut::kTargetClass_RoboRIO2) {
+    runtimeType = HAL_Runtime_RoboRIO2;
+  } else {
+    runtimeType = HAL_Runtime_RoboRIO;
+  }
+
   InterruptManager::Initialize(global->getSystemInterface());
 
   hal::InitializeDriverStation();
@@ -531,20 +597,7 @@
     return false;
   }
 
-  // Set WPI_Now to use FPGA timestamp
-  wpi::SetNowImpl([]() -> uint64_t {
-    int32_t status = 0;
-    uint64_t rv = HAL_GetFPGATime(&status);
-    if (status != 0) {
-      fmt::print(stderr,
-                 "Call to HAL_GetFPGATime failed in wpi::Now() with status {}. "
-                 "Initialization might have failed. Time will not be correct\n",
-                 status);
-      std::fflush(stderr);
-      return 0u;
-    }
-    return rv;
-  });
+  hal::WaitForInitialPacket();
 
   initialized = true;
   return true;
diff --git a/hal/src/main/native/athena/HMB.cpp b/hal/src/main/native/athena/HMB.cpp
new file mode 100644
index 0000000..d22fcda
--- /dev/null
+++ b/hal/src/main/native/athena/HMB.cpp
@@ -0,0 +1,82 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "hal/roborio/HMB.h"
+
+#include <memory>
+
+#include "FPGACalls.h"
+#include "hal/ChipObject.h"
+
+using namespace hal;
+
+// 16 classes of data, each takes up 16 uint16_t's
+static_assert(sizeof(HAL_HMBData) == 0x10 * 16 * sizeof(uint32_t));
+// Timestamp is the last class, and should be offset correctly
+static_assert(offsetof(HAL_HMBData, Timestamp) == 0x10 * 15 * sizeof(uint32_t));
+
+static volatile HAL_HMBData* hmbBuffer;
+static size_t hmbBufferSize;
+static constexpr const char hmbName[] = "HMB_0_RAM";
+static std::unique_ptr<tHMB> hmb;
+
+namespace {
+struct HMBHolder {
+  ~HMBHolder() {
+    if (hmbBuffer) {
+      hal::HAL_NiFpga_CloseHmb(hmb->getSystemInterface()->getHandle(), hmbName);
+    }
+  }
+};
+}  // namespace
+
+extern "C" {
+
+void HAL_InitializeHMB(int32_t* status) {
+  static HMBHolder holder;
+
+  hmb.reset(tHMB::create(status));
+  if (*status != 0) {
+    return;
+  }
+
+  *status = hal::HAL_NiFpga_OpenHmb(
+      hmb->getSystemInterface()->getHandle(), hmbName, &hmbBufferSize,
+      reinterpret_cast<void**>(const_cast<HAL_HMBData**>(&hmbBuffer)));
+
+  if (*status != 0) {
+    return;
+  }
+
+  auto cfg = hmb->readConfig(status);
+  cfg.Enables_AI0_Low = 1;
+  cfg.Enables_AI0_High = 1;
+  cfg.Enables_AIAveraged0_Low = 1;
+  cfg.Enables_AIAveraged0_High = 1;
+  cfg.Enables_Accumulator0 = 1;
+  cfg.Enables_Accumulator1 = 1;
+  cfg.Enables_DI = 1;
+  cfg.Enables_AnalogTriggers = 1;
+  cfg.Enables_Counters_Low = 1;
+  cfg.Enables_Counters_High = 1;
+  cfg.Enables_CounterTimers_Low = 1;
+  cfg.Enables_CounterTimers_High = 1;
+  cfg.Enables_Encoders_Low = 1;
+  cfg.Enables_Encoders_High = 1;
+  cfg.Enables_EncoderTimers_Low = 1;
+  cfg.Enables_EncoderTimers_High = 1;
+  cfg.Enables_DutyCycle_Low = 1;
+  cfg.Enables_DutyCycle_High = 1;
+  cfg.Enables_Interrupts = 1;
+  cfg.Enables_PWM = 1;
+  cfg.Enables_PWM_MXP = 1;
+  cfg.Enables_Relay_DO_AO = 1;
+  cfg.Enables_Timestamp = 1;
+  hmb->writeConfig(cfg, status);
+}
+
+const volatile HAL_HMBData* HAL_GetHMBBuffer(void) {
+  return hmbBuffer;
+}
+}  // extern "C"
diff --git a/hal/src/main/native/athena/Notifier.cpp b/hal/src/main/native/athena/Notifier.cpp
index 9c818d8..bed998d 100644
--- a/hal/src/main/native/athena/Notifier.cpp
+++ b/hal/src/main/native/athena/Notifier.cpp
@@ -128,8 +128,9 @@
 
 static void cleanupNotifierAtExit() {
   int32_t status = 0;
-  if (notifierAlarm)
+  if (notifierAlarm) {
     notifierAlarm->writeEnable(false, &status);
+  }
   notifierAlarm = nullptr;
   notifierRunning = false;
   hal::ReleaseFPGAInterrupt(kTimerInterruptNumber);
@@ -236,8 +237,9 @@
     // here (the atomic fetch_sub will prevent multiple parallel entries
     // into this function)
 
-    if (notifierAlarm)
+    if (notifierAlarm) {
       notifierAlarm->writeEnable(false, status);
+    }
     notifierRunning = false;
     hal::ReleaseFPGAInterrupt(kTimerInterruptNumber);
     if (notifierThread.joinable()) {
@@ -272,8 +274,9 @@
     notifierAlarm->writeTriggerTime(static_cast<uint32_t>(closestTrigger),
                                     status);
     // Enable the alarm.
-    if (!wasActive)
+    if (!wasActive) {
       notifierAlarm->writeEnable(true, status);
+    }
   }
 }
 
diff --git a/hal/src/main/native/athena/PWM.cpp b/hal/src/main/native/athena/PWM.cpp
index 19a3b83..bb6f7dd 100644
--- a/hal/src/main/native/athena/PWM.cpp
+++ b/hal/src/main/native/athena/PWM.cpp
@@ -9,6 +9,8 @@
 #include <cstdio>
 #include <thread>
 
+#include <fmt/format.h>
+
 #include "ConstantsInternal.h"
 #include "DigitalInternal.h"
 #include "HALInitializer.h"
@@ -118,7 +120,7 @@
   }
 
   // Defaults to allow an always valid config.
-  HAL_SetPWMConfig(handle, 2.0, 1.501, 1.5, 1.499, 1.0, status);
+  HAL_SetPWMConfigMicroseconds(handle, 2000, 1501, 1500, 1499, 1000, status);
 
   port->previousAllocation = allocationLocation ? allocationLocation : "";
 
@@ -158,62 +160,28 @@
   return channel < kNumPWMChannels && channel >= 0;
 }
 
-void HAL_SetPWMConfig(HAL_DigitalHandle pwmPortHandle, double max,
-                      double deadbandMax, double center, double deadbandMin,
-                      double min, int32_t* status) {
+void HAL_SetPWMConfigMicroseconds(HAL_DigitalHandle pwmPortHandle, int32_t max,
+                                  int32_t deadbandMax, int32_t center,
+                                  int32_t deadbandMin, int32_t min,
+                                  int32_t* status) {
   auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
   if (port == nullptr) {
     *status = HAL_HANDLE_ERROR;
     return;
   }
 
-  // calculate the loop time in milliseconds
-  double loopTime =
-      HAL_GetPWMLoopTiming(status) / (kSystemClockTicksPerMicrosecond * 1e3);
-  if (*status != 0) {
-    return;
-  }
-
-  int32_t maxPwm = static_cast<int32_t>((max - kDefaultPwmCenter) / loopTime +
-                                        kDefaultPwmStepsDown - 1);
-  int32_t deadbandMaxPwm = static_cast<int32_t>(
-      (deadbandMax - kDefaultPwmCenter) / loopTime + kDefaultPwmStepsDown - 1);
-  int32_t centerPwm = static_cast<int32_t>(
-      (center - kDefaultPwmCenter) / loopTime + kDefaultPwmStepsDown - 1);
-  int32_t deadbandMinPwm = static_cast<int32_t>(
-      (deadbandMin - kDefaultPwmCenter) / loopTime + kDefaultPwmStepsDown - 1);
-  int32_t minPwm = static_cast<int32_t>((min - kDefaultPwmCenter) / loopTime +
-                                        kDefaultPwmStepsDown - 1);
-
-  port->maxPwm = maxPwm;
-  port->deadbandMaxPwm = deadbandMaxPwm;
-  port->deadbandMinPwm = deadbandMinPwm;
-  port->centerPwm = centerPwm;
-  port->minPwm = minPwm;
+  port->maxPwm = max;
+  port->deadbandMaxPwm = deadbandMax;
+  port->deadbandMinPwm = deadbandMin;
+  port->centerPwm = center;
+  port->minPwm = min;
   port->configSet = true;
 }
 
-void HAL_SetPWMConfigRaw(HAL_DigitalHandle pwmPortHandle, int32_t maxPwm,
-                         int32_t deadbandMaxPwm, int32_t centerPwm,
-                         int32_t deadbandMinPwm, int32_t minPwm,
-                         int32_t* status) {
-  auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
-  if (port == nullptr) {
-    *status = HAL_HANDLE_ERROR;
-    return;
-  }
-
-  port->maxPwm = maxPwm;
-  port->deadbandMaxPwm = deadbandMaxPwm;
-  port->deadbandMinPwm = deadbandMinPwm;
-  port->centerPwm = centerPwm;
-  port->minPwm = minPwm;
-}
-
-void HAL_GetPWMConfigRaw(HAL_DigitalHandle pwmPortHandle, int32_t* maxPwm,
-                         int32_t* deadbandMaxPwm, int32_t* centerPwm,
-                         int32_t* deadbandMinPwm, int32_t* minPwm,
-                         int32_t* status) {
+void HAL_GetPWMConfigMicroseconds(HAL_DigitalHandle pwmPortHandle,
+                                  int32_t* maxPwm, int32_t* deadbandMaxPwm,
+                                  int32_t* centerPwm, int32_t* deadbandMinPwm,
+                                  int32_t* minPwm, int32_t* status) {
   auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
   if (port == nullptr) {
     *status = HAL_HANDLE_ERROR;
@@ -246,18 +214,30 @@
   return port->eliminateDeadband;
 }
 
-void HAL_SetPWMRaw(HAL_DigitalHandle pwmPortHandle, int32_t value,
-                   int32_t* status) {
+void HAL_SetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
+                                     int32_t microsecondPulseTime,
+                                     int32_t* status) {
   auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
   if (port == nullptr) {
     *status = HAL_HANDLE_ERROR;
     return;
   }
 
+  if (microsecondPulseTime < 0 ||
+      (microsecondPulseTime != 0xFFFF && microsecondPulseTime >= 4096)) {
+    *status = PARAMETER_OUT_OF_RANGE;
+    hal::SetLastError(
+        status,
+        fmt::format("Pulse time {} out of range. Expect [0-4096) or 0xFFFF",
+                    microsecondPulseTime));
+    return;
+  }
+
   if (port->channel < tPWM::kNumHdrRegisters) {
-    pwmSystem->writeHdr(port->channel, value, status);
+    pwmSystem->writeHdr(port->channel, microsecondPulseTime, status);
   } else {
-    pwmSystem->writeMXP(port->channel - tPWM::kNumHdrRegisters, value, status);
+    pwmSystem->writeMXP(port->channel - tPWM::kNumHdrRegisters,
+                        microsecondPulseTime, status);
   }
 }
 
@@ -302,7 +282,7 @@
     return;
   }
 
-  HAL_SetPWMRaw(pwmPortHandle, rawValue, status);
+  HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, rawValue, status);
 }
 
 void HAL_SetPWMPosition(HAL_DigitalHandle pwmPortHandle, double pos,
@@ -335,14 +315,15 @@
     return;
   }
 
-  HAL_SetPWMRaw(pwmPortHandle, rawValue, status);
+  HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, rawValue, status);
 }
 
 void HAL_SetPWMDisabled(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
-  HAL_SetPWMRaw(pwmPortHandle, kPwmDisabled, status);
+  HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, kPwmDisabled, status);
 }
 
-int32_t HAL_GetPWMRaw(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
+int32_t HAL_GetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
+                                        int32_t* status) {
   auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
   if (port == nullptr) {
     *status = HAL_HANDLE_ERROR;
@@ -367,12 +348,11 @@
     return 0;
   }
 
-  int32_t value = HAL_GetPWMRaw(pwmPortHandle, status);
+  int32_t value = HAL_GetPWMPulseTimeMicroseconds(pwmPortHandle, status);
   if (*status != 0) {
     return 0;
   }
   DigitalPort* dPort = port.get();
-
   if (value == kPwmDisabled) {
     return 0.0;
   } else if (value > GetMaxPositivePwm(dPort)) {
@@ -401,7 +381,7 @@
     return 0;
   }
 
-  int32_t value = HAL_GetPWMRaw(pwmPortHandle, status);
+  int32_t value = HAL_GetPWMPulseTimeMicroseconds(pwmPortHandle, status);
   if (*status != 0) {
     return 0;
   }
@@ -444,6 +424,11 @@
   }
 }
 
+void HAL_SetPWMAlwaysHighMode(HAL_DigitalHandle pwmPortHandle,
+                              int32_t* status) {
+  HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, kPwmAlwaysHigh, status);
+}
+
 int32_t HAL_GetPWMLoopTiming(int32_t* status) {
   initializeDigital(status);
   if (*status != 0) {
diff --git a/hal/src/main/native/athena/Power.cpp b/hal/src/main/native/athena/Power.cpp
index e911d5d..249ab98 100644
--- a/hal/src/main/native/athena/Power.cpp
+++ b/hal/src/main/native/athena/Power.cpp
@@ -61,6 +61,11 @@
       power->readFaultCounts_OverCurrentFaultCount6V(status));
 }
 
+void HAL_SetUserRailEnabled6V(HAL_Bool enabled, int32_t* status) {
+  initializePower(status);
+  power->writeDisable_User6V(!enabled, status);
+}
+
 double HAL_GetUserVoltage5V(int32_t* status) {
   initializePower(status);
   return power->readUserVoltage5V(status) / 4.096 * 0.005962 - 0.013;
@@ -82,6 +87,11 @@
       power->readFaultCounts_OverCurrentFaultCount5V(status));
 }
 
+void HAL_SetUserRailEnabled5V(HAL_Bool enabled, int32_t* status) {
+  initializePower(status);
+  power->writeDisable_User5V(!enabled, status);
+}
+
 double HAL_GetUserVoltage3V3(int32_t* status) {
   initializePower(status);
   return power->readUserVoltage3V3(status) / 4.096 * 0.004902 - 0.01;
@@ -103,6 +113,11 @@
       power->readFaultCounts_OverCurrentFaultCount3V3(status));
 }
 
+void HAL_SetUserRailEnabled3V3(HAL_Bool enabled, int32_t* status) {
+  initializePower(status);
+  power->writeDisable_User3V3(!enabled, status);
+}
+
 void HAL_SetBrownoutVoltage(double voltage, int32_t* status) {
   initializePower(status);
   if (voltage < 0) {
@@ -121,4 +136,9 @@
   return brownout / 4.0;
 }
 
+double HAL_GetCPUTemp(int32_t* status) {
+  initializePower(status);
+  return power->readOnChipTemperature(status) / 4096.0 * 503.975 - 273.15;
+}
+
 }  // extern "C"
diff --git a/hal/src/main/native/athena/SPI.cpp b/hal/src/main/native/athena/SPI.cpp
index 9d3335e..309813e 100644
--- a/hal/src/main/native/athena/SPI.cpp
+++ b/hal/src/main/native/athena/SPI.cpp
@@ -643,8 +643,9 @@
   }
 
   // set tx data registers
-  for (int32_t i = 0; i < dataSize; ++i)
+  for (int32_t i = 0; i < dataSize; ++i) {
     spiSystem->writeAutoTx(i >> 2, i & 3, dataToSend[i], status);
+  }
 
   // set byte counts
   tSPI::tAutoByteCount config;
diff --git a/hal/src/main/native/athena/SimDevice.cpp b/hal/src/main/native/athena/SimDevice.cpp
index 3a15f46..03b35f7 100644
--- a/hal/src/main/native/athena/SimDevice.cpp
+++ b/hal/src/main/native/athena/SimDevice.cpp
@@ -12,6 +12,10 @@
 
 void HAL_FreeSimDevice(HAL_SimDeviceHandle handle) {}
 
+const char* HAL_GetSimDeviceName(HAL_SimDeviceHandle handle) {
+  return "";
+}
+
 HAL_SimValueHandle HAL_CreateSimValue(HAL_SimDeviceHandle device,
                                       const char* name, int32_t direction,
                                       const struct HAL_Value* initialValue) {
diff --git a/hal/src/main/native/athena/cpp/SerialHelper.cpp b/hal/src/main/native/athena/cpp/SerialHelper.cpp
index fef92d4..71e747c 100644
--- a/hal/src/main/native/athena/cpp/SerialHelper.cpp
+++ b/hal/src/main/native/athena/cpp/SerialHelper.cpp
@@ -192,45 +192,54 @@
     // Open the resource, grab its interface name, and close it.
     ViSession vSession;
     *status = viOpen(m_resourceHandle, desc, VI_NULL, VI_NULL, &vSession);
-    if (*status < 0)
+    if (*status < 0) {
       continue;
+    }
     *status = 0;
 
     *status = viGetAttribute(vSession, VI_ATTR_INTF_INST_NAME, &osName);
     // Ignore an error here, as we want to close the session on an error
     // Use a separate close variable so we can check
     ViStatus closeStatus = viClose(vSession);
-    if (*status < 0)
+    if (*status < 0) {
       continue;
-    if (closeStatus < 0)
+    }
+    if (closeStatus < 0) {
       continue;
+    }
     *status = 0;
 
     // split until (/dev/
     std::string_view devNameRef = wpi::split(osName, "(/dev/").second;
     // String not found, continue
-    if (wpi::equals(devNameRef, ""))
+    if (wpi::equals(devNameRef, "")) {
       continue;
+    }
 
     // Split at )
     std::string_view matchString = wpi::split(devNameRef, ')').first;
-    if (wpi::equals(matchString, devNameRef))
+    if (wpi::equals(matchString, devNameRef)) {
       continue;
+    }
 
     // Search directories to get a list of system accessors
     // The directories we need are not symbolic, so we can safely
     // disable symbolic links.
     std::error_code ec;
     for (auto& p : fs::recursive_directory_iterator("/sys/devices/soc0", ec)) {
-      if (ec)
+      if (ec) {
         break;
+      }
       std::string path = p.path();
-      if (path.find("amba") == std::string::npos)
+      if (path.find("amba") == std::string::npos) {
         continue;
-      if (path.find("usb") == std::string::npos)
+      }
+      if (path.find("usb") == std::string::npos) {
         continue;
-      if (path.find(matchString) == std::string::npos)
+      }
+      if (path.find(matchString) == std::string::npos) {
         continue;
+      }
 
       wpi::SmallVector<std::string_view, 16> pathSplitVec;
       // Split path into individual directories
@@ -254,13 +263,15 @@
 
       // Get the index for our device
       int hubIndex = findtty;
-      if (findtty == -1)
+      if (findtty == -1) {
         hubIndex = findregex;
+      }
 
       int devStart = findusb + 1;
 
-      if (hubIndex < devStart)
+      if (hubIndex < devStart) {
         continue;
+      }
 
       // Add our devices to our list
       m_unsortedHubPath.emplace_back(
diff --git a/hal/src/main/native/athena/frccansae/CANDeviceInterface.h b/hal/src/main/native/athena/frccansae/CANDeviceInterface.h
index 8fe4235..d9c9a0c 100644
--- a/hal/src/main/native/athena/frccansae/CANDeviceInterface.h
+++ b/hal/src/main/native/athena/frccansae/CANDeviceInterface.h
@@ -51,7 +51,7 @@
    // Bootloader version.  Will not change for the life of the product, but additional
    // field upgrade features could be added in newer hardware.
    char bootloaderRev[MAX_STRING_LEN];
-   // Manufacture Date.  Could be a calender date or just the FRC season year.
+   // Manufacture Date.  Could be a calendar date or just the FRC season year.
    // Also helps troubleshooting "old ones" vs "new ones".
    char manufactureDate[MAX_STRING_LEN];
    // General status of the hardware.  For example if the device is in bootloader
diff --git a/hal/src/main/native/athena/mockdata/PWMData.cpp b/hal/src/main/native/athena/mockdata/PWMData.cpp
index 3e12398..4fb6bcf 100644
--- a/hal/src/main/native/athena/mockdata/PWMData.cpp
+++ b/hal/src/main/native/athena/mockdata/PWMData.cpp
@@ -13,7 +13,7 @@
   HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, PWM##CAPINAME, RETURN)
 
 DEFINE_CAPI(HAL_Bool, Initialized, false)
-DEFINE_CAPI(int32_t, RawValue, 0)
+DEFINE_CAPI(int32_t, PulseMicrosecond, 0)
 DEFINE_CAPI(double, Speed, 0)
 DEFINE_CAPI(double, Position, 0)
 DEFINE_CAPI(int32_t, PeriodScale, 0)
diff --git a/hal/src/main/native/athena/mockdata/RoboRioData.cpp b/hal/src/main/native/athena/mockdata/RoboRioData.cpp
index 9392fcb..8559394 100644
--- a/hal/src/main/native/athena/mockdata/RoboRioData.cpp
+++ b/hal/src/main/native/athena/mockdata/RoboRioData.cpp
@@ -28,6 +28,8 @@
 DEFINE_CAPI(int32_t, UserFaults5V, 0)
 DEFINE_CAPI(int32_t, UserFaults3V3, 0)
 DEFINE_CAPI(double, BrownoutVoltage, 6.75)
+DEFINE_CAPI(double, CPUTemp, 45.0)
+DEFINE_CAPI(int32_t, TeamNumber, 0)
 
 int32_t HALSIM_RegisterRoboRioSerialNumberCallback(
     HAL_RoboRioStringCallback callback, void* param, HAL_Bool initialNotify) {
diff --git a/hal/src/main/native/athena/rev/PHFrames.h b/hal/src/main/native/athena/rev/PHFrames.h
index 20411a8..a1849e1 100644
--- a/hal/src/main/native/athena/rev/PHFrames.h
+++ b/hal/src/main/native/athena/rev/PHFrames.h
@@ -79,7 +79,7 @@
 /**

  * Signals in message Compressor_Config.

  *

- * Configures compressor to use digitial/analog sensors

+ * Configures compressor to use digital/analog sensors

  *

  * All signal values are as on the CAN bus.

  */

diff --git a/hal/src/main/native/cpp/jni/AddressableLEDJNI.cpp b/hal/src/main/native/cpp/jni/AddressableLEDJNI.cpp
index 75da176..66e3ed0 100644
--- a/hal/src/main/native/cpp/jni/AddressableLEDJNI.cpp
+++ b/hal/src/main/native/cpp/jni/AddressableLEDJNI.cpp
@@ -69,12 +69,11 @@
   (JNIEnv* env, jclass, jint handle, jbyteArray arr)
 {
   int32_t status = 0;
-  JByteArrayRef jArrRef{env, arr};
-  auto arrRef = jArrRef.array();
+  JSpan<const jbyte> jArrRef{env, arr};
   HAL_WriteAddressableLEDData(
       static_cast<HAL_AddressableLEDHandle>(handle),
-      reinterpret_cast<const HAL_AddressableLEDData*>(arrRef.data()),
-      arrRef.size() / 4, &status);
+      reinterpret_cast<const HAL_AddressableLEDData*>(jArrRef.data()),
+      jArrRef.size() / 4, &status);
   CheckStatus(env, status);
 }
 
@@ -85,12 +84,12 @@
  */
 JNIEXPORT void JNICALL
 Java_edu_wpi_first_hal_AddressableLEDJNI_setBitTiming
-  (JNIEnv* env, jclass, jint handle, jint lowTime0, jint highTime0,
-   jint lowTime1, jint highTime1)
+  (JNIEnv* env, jclass, jint handle, jint highTime0, jint lowTime0,
+   jint highTime1, jint lowTime1)
 {
   int32_t status = 0;
   HAL_SetAddressableLEDBitTiming(static_cast<HAL_AddressableLEDHandle>(handle),
-                                 lowTime0, highTime0, lowTime1, highTime1,
+                                 highTime0, lowTime0, highTime1, lowTime1,
                                  &status);
   CheckStatus(env, status);
 }
diff --git a/hal/src/main/native/cpp/jni/CANAPIJNI.cpp b/hal/src/main/native/cpp/jni/CANAPIJNI.cpp
index 106167a..929f7da 100644
--- a/hal/src/main/native/cpp/jni/CANAPIJNI.cpp
+++ b/hal/src/main/native/cpp/jni/CANAPIJNI.cpp
@@ -18,6 +18,18 @@
 using namespace wpi::java;
 
 extern "C" {
+
+/*
+ * Class:     edu_wpi_first_hal_CANAPIJNI
+ * Method:    getCANPacketBaseTime
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL
+Java_edu_wpi_first_hal_CANAPIJNI_getCANPacketBaseTime
+  (JNIEnv*, jclass)
+{
+  return HAL_GetCANPacketBaseTime();
+}
 /*
  * Class:     edu_wpi_first_hal_CANAPIJNI
  * Method:    initializeCAN
@@ -59,11 +71,10 @@
   (JNIEnv* env, jclass, jint handle, jbyteArray data, jint apiId)
 {
   auto halHandle = static_cast<HAL_CANHandle>(handle);
-  JByteArrayRef arr{env, data};
-  auto arrRef = arr.array();
+  JSpan<const jbyte> arr{env, data};
   int32_t status = 0;
-  HAL_WriteCANPacket(halHandle, reinterpret_cast<const uint8_t*>(arrRef.data()),
-                     arrRef.size(), apiId, &status);
+  HAL_WriteCANPacket(halHandle, reinterpret_cast<const uint8_t*>(arr.data()),
+                     arr.size(), apiId, &status);
   CheckStatus(env, status);
 }
 
@@ -78,12 +89,11 @@
    jint timeoutMs)
 {
   auto halHandle = static_cast<HAL_CANHandle>(handle);
-  JByteArrayRef arr{env, data};
-  auto arrRef = arr.array();
+  JSpan<const jbyte> arr{env, data};
   int32_t status = 0;
   HAL_WriteCANPacketRepeating(halHandle,
-                              reinterpret_cast<const uint8_t*>(arrRef.data()),
-                              arrRef.size(), apiId, timeoutMs, &status);
+                              reinterpret_cast<const uint8_t*>(arr.data()),
+                              arr.size(), apiId, timeoutMs, &status);
   CheckStatus(env, status);
 }
 
@@ -112,11 +122,10 @@
   (JNIEnv* env, jclass, jint handle, jbyteArray data, jint apiId)
 {
   auto halHandle = static_cast<HAL_CANHandle>(handle);
-  JByteArrayRef arr{env, data};
-  auto arrRef = arr.array();
+  JSpan<const jbyte> arr{env, data};
   int32_t status = 0;
-  HAL_WriteCANPacket(halHandle, reinterpret_cast<const uint8_t*>(arrRef.data()),
-                     arrRef.size(), apiId, &status);
+  HAL_WriteCANPacket(halHandle, reinterpret_cast<const uint8_t*>(arr.data()),
+                     arr.size(), apiId, &status);
   return status;
 }
 
@@ -131,12 +140,11 @@
    jint timeoutMs)
 {
   auto halHandle = static_cast<HAL_CANHandle>(handle);
-  JByteArrayRef arr{env, data};
-  auto arrRef = arr.array();
+  JSpan<const jbyte> arr{env, data};
   int32_t status = 0;
   HAL_WriteCANPacketRepeating(halHandle,
-                              reinterpret_cast<const uint8_t*>(arrRef.data()),
-                              arrRef.size(), apiId, timeoutMs, &status);
+                              reinterpret_cast<const uint8_t*>(arr.data()),
+                              arr.size(), apiId, timeoutMs, &status);
   return status;
 }
 
diff --git a/hal/src/main/native/cpp/jni/CANJNI.cpp b/hal/src/main/native/cpp/jni/CANJNI.cpp
index 4ad2a74..9375a06 100644
--- a/hal/src/main/native/cpp/jni/CANJNI.cpp
+++ b/hal/src/main/native/cpp/jni/CANJNI.cpp
@@ -26,11 +26,11 @@
 Java_edu_wpi_first_hal_can_CANJNI_FRCNetCommCANSessionMuxSendMessage
   (JNIEnv* env, jclass, jint messageID, jbyteArray data, jint periodMs)
 {
-  JByteArrayRef dataArray{env, data};
+  JSpan<const jbyte> dataArray{env, data};
 
   const uint8_t* dataBuffer =
-      reinterpret_cast<const uint8_t*>(dataArray.array().data());
-  uint8_t dataSize = dataArray.array().size();
+      reinterpret_cast<const uint8_t*>(dataArray.data());
+  uint8_t dataSize = dataArray.size();
 
   int32_t status = 0;
   HAL_CAN_SendMessage(messageID, dataBuffer, dataSize, periodMs, &status);
diff --git a/hal/src/main/native/cpp/jni/DMAJNI.cpp b/hal/src/main/native/cpp/jni/DMAJNI.cpp
index 3e95c7b..79dc14b 100644
--- a/hal/src/main/native/cpp/jni/DMAJNI.cpp
+++ b/hal/src/main/native/cpp/jni/DMAJNI.cpp
@@ -5,12 +5,15 @@
 #include <algorithm>
 #include <cstring>
 
+#include <wpi/jni_util.h>
+
 #include "HALUtil.h"
 #include "edu_wpi_first_hal_DMAJNI.h"
 #include "hal/DMA.h"
 #include "hal/handles/HandlesInternal.h"
 
 using namespace hal;
+using namespace wpi::java;
 
 namespace hal {
 bool GetEncoderBaseHandle(HAL_EncoderHandle handle,
@@ -312,20 +315,17 @@
   env->SetIntArrayRegion(buf, 0, dmaSample.captureSize,
                          reinterpret_cast<jint*>(dmaSample.readBuffer));
 
-  int32_t* nativeArr =
-      static_cast<int32_t*>(env->GetPrimitiveArrayCritical(store, nullptr));
+  CriticalJSpan<jint> nativeArr{env, store};
 
   std::copy_n(
       dmaSample.channelOffsets,
       sizeof(dmaSample.channelOffsets) / sizeof(dmaSample.channelOffsets[0]),
-      nativeArr);
+      nativeArr.data());
   nativeArr[22] = static_cast<int32_t>(dmaSample.captureSize);
   nativeArr[23] = static_cast<int32_t>(dmaSample.triggerChannels);
   nativeArr[24] = remaining;
   nativeArr[25] = readStatus;
 
-  env->ReleasePrimitiveArrayCritical(store, nativeArr, JNI_ABORT);
-
   return dmaSample.timeStamp;
 }
 
diff --git a/hal/src/main/native/cpp/jni/DriverStationJNI.cpp b/hal/src/main/native/cpp/jni/DriverStationJNI.cpp
index f050f02..5e3e97f 100644
--- a/hal/src/main/native/cpp/jni/DriverStationJNI.cpp
+++ b/hal/src/main/native/cpp/jni/DriverStationJNI.cpp
@@ -15,7 +15,27 @@
 #include "hal/FRCUsageReporting.h"
 #include "hal/HALBase.h"
 
-// TODO Static asserts
+static_assert(edu_wpi_first_hal_DriverStationJNI_kUnknownAllianceStation ==
+              HAL_AllianceStationID_kUnknown);
+static_assert(edu_wpi_first_hal_DriverStationJNI_kRed1AllianceStation ==
+              HAL_AllianceStationID_kRed1);
+static_assert(edu_wpi_first_hal_DriverStationJNI_kRed2AllianceStation ==
+              HAL_AllianceStationID_kRed2);
+static_assert(edu_wpi_first_hal_DriverStationJNI_kRed3AllianceStation ==
+              HAL_AllianceStationID_kRed3);
+static_assert(edu_wpi_first_hal_DriverStationJNI_kBlue1AllianceStation ==
+              HAL_AllianceStationID_kBlue1);
+static_assert(edu_wpi_first_hal_DriverStationJNI_kBlue2AllianceStation ==
+              HAL_AllianceStationID_kBlue2);
+static_assert(edu_wpi_first_hal_DriverStationJNI_kBlue3AllianceStation ==
+              HAL_AllianceStationID_kBlue3);
+
+static_assert(edu_wpi_first_hal_DriverStationJNI_kMaxJoystickAxes ==
+              HAL_kMaxJoystickAxes);
+static_assert(edu_wpi_first_hal_DriverStationJNI_kMaxJoystickPOVs ==
+              HAL_kMaxJoystickPOVs);
+static_assert(edu_wpi_first_hal_DriverStationJNI_kMaxJoysticks ==
+              HAL_kMaxJoysticks);
 
 using namespace hal;
 using namespace wpi::java;
@@ -231,10 +251,10 @@
 
   HAL_GetAllJoystickData(axes, povs, buttons);
 
-  CriticalJFloatArrayRef jAxes(env, axesArray);
-  CriticalJByteArrayRef jRawAxes(env, rawAxesArray);
-  CriticalJShortArrayRef jPovs(env, povsArray);
-  CriticalJLongArrayRef jButtons(env, buttonsAndMetadataArray);
+  CriticalJSpan<jfloat> jAxes(env, axesArray);
+  CriticalJSpan<jbyte> jRawAxes(env, rawAxesArray);
+  CriticalJSpan<jshort> jPovs(env, povsArray);
+  CriticalJSpan<jlong> jButtons(env, buttonsAndMetadataArray);
 
   static_assert(sizeof(jAxes[0]) == sizeof(axes[0].axes[0]));
   static_assert(sizeof(jRawAxes[0]) == sizeof(axes[0].raw[0]));
@@ -403,13 +423,13 @@
 /*
  * Class:     edu_wpi_first_hal_DriverStationJNI
  * Method:    refreshDSData
- * Signature: ()V
+ * Signature: ()Z
  */
-JNIEXPORT void JNICALL
+JNIEXPORT jboolean JNICALL
 Java_edu_wpi_first_hal_DriverStationJNI_refreshDSData
   (JNIEnv*, jclass)
 {
-  HAL_RefreshDSData();
+  return HAL_RefreshDSData();
 }
 
 /*
diff --git a/hal/src/main/native/cpp/jni/HAL.cpp b/hal/src/main/native/cpp/jni/HAL.cpp
index b603a76..6f486e5 100644
--- a/hal/src/main/native/cpp/jni/HAL.cpp
+++ b/hal/src/main/native/cpp/jni/HAL.cpp
@@ -138,6 +138,36 @@
 
 /*
  * Class:     edu_wpi_first_hal_HAL
+ * Method:    getRSLState
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_edu_wpi_first_hal_HAL_getRSLState
+  (JNIEnv* env, jclass)
+{
+  int32_t status = 0;
+  bool val = HAL_GetRSLState(&status);
+  CheckStatus(env, status);
+  return val;
+}
+
+/*
+ * Class:     edu_wpi_first_hal_HAL
+ * Method:    getSystemTimeValid
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_edu_wpi_first_hal_HAL_getSystemTimeValid
+  (JNIEnv* env, jclass)
+{
+  int32_t status = 0;
+  bool val = HAL_GetSystemTimeValid(&status);
+  CheckStatus(env, status);
+  return val;
+}
+
+/*
+ * Class:     edu_wpi_first_hal_HAL
  * Method:    getPortWithModule
  * Signature: (BB)I
  */
diff --git a/hal/src/main/native/cpp/jni/HALUtil.cpp b/hal/src/main/native/cpp/jni/HALUtil.cpp
index 76c05f8..6316a8c 100644
--- a/hal/src/main/native/cpp/jni/HALUtil.cpp
+++ b/hal/src/main/native/cpp/jni/HALUtil.cpp
@@ -486,6 +486,18 @@
 
 /*
  * Class:     edu_wpi_first_hal_HALUtil
+ * Method:    getTeamNumber
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL
+Java_edu_wpi_first_hal_HALUtil_getTeamNumber
+  (JNIEnv* env, jclass)
+{
+  return HAL_GetTeamNumber();
+}
+
+/*
+ * Class:     edu_wpi_first_hal_HALUtil
  * Method:    getFPGATime
  * Signature: ()J
  */
diff --git a/hal/src/main/native/cpp/jni/I2CJNI.cpp b/hal/src/main/native/cpp/jni/I2CJNI.cpp
index 68b8442..6e06bb8 100644
--- a/hal/src/main/native/cpp/jni/I2CJNI.cpp
+++ b/hal/src/main/native/cpp/jni/I2CJNI.cpp
@@ -79,7 +79,7 @@
   jint returnValue =
       HAL_TransactionI2C(static_cast<HAL_I2CPort>(port), address,
                          reinterpret_cast<const uint8_t*>(
-                             JByteArrayRef(env, dataToSend).array().data()),
+                             JSpan<const jbyte>(env, dataToSend).data()),
                          sendSize, recvBuf.data(), receiveSize);
   env->SetByteArrayRegion(dataReceived, 0, receiveSize,
                           reinterpret_cast<const jbyte*>(recvBuf.data()));
@@ -120,7 +120,7 @@
   jint returnValue =
       HAL_WriteI2C(static_cast<HAL_I2CPort>(port), address,
                    reinterpret_cast<const uint8_t*>(
-                       JByteArrayRef(env, dataToSend).array().data()),
+                       JSpan<const jbyte>(env, dataToSend).data()),
                    sendSize);
   return returnValue;
 }
diff --git a/hal/src/main/native/cpp/jni/PWMJNI.cpp b/hal/src/main/native/cpp/jni/PWMJNI.cpp
index e83f11b..2f90ded 100644
--- a/hal/src/main/native/cpp/jni/PWMJNI.cpp
+++ b/hal/src/main/native/cpp/jni/PWMJNI.cpp
@@ -63,43 +63,27 @@
 
 /*
  * Class:     edu_wpi_first_hal_PWMJNI
- * Method:    setPWMConfigRaw
+ * Method:    setPWMConfigMicroseconds
  * Signature: (IIIIII)V
  */
 JNIEXPORT void JNICALL
-Java_edu_wpi_first_hal_PWMJNI_setPWMConfigRaw
+Java_edu_wpi_first_hal_PWMJNI_setPWMConfigMicroseconds
   (JNIEnv* env, jclass, jint id, jint maxPwm, jint deadbandMaxPwm,
    jint centerPwm, jint deadbandMinPwm, jint minPwm)
 {
   int32_t status = 0;
-  HAL_SetPWMConfigRaw((HAL_DigitalHandle)id, maxPwm, deadbandMaxPwm, centerPwm,
-                      deadbandMinPwm, minPwm, &status);
+  HAL_SetPWMConfigMicroseconds((HAL_DigitalHandle)id, maxPwm, deadbandMaxPwm,
+                               centerPwm, deadbandMinPwm, minPwm, &status);
   CheckStatus(env, status);
 }
 
 /*
  * Class:     edu_wpi_first_hal_PWMJNI
- * Method:    setPWMConfig
- * Signature: (IDDDDD)V
- */
-JNIEXPORT void JNICALL
-Java_edu_wpi_first_hal_PWMJNI_setPWMConfig
-  (JNIEnv* env, jclass, jint id, jdouble maxPwm, jdouble deadbandMaxPwm,
-   jdouble centerPwm, jdouble deadbandMinPwm, jdouble minPwm)
-{
-  int32_t status = 0;
-  HAL_SetPWMConfig((HAL_DigitalHandle)id, maxPwm, deadbandMaxPwm, centerPwm,
-                   deadbandMinPwm, minPwm, &status);
-  CheckStatus(env, status);
-}
-
-/*
- * Class:     edu_wpi_first_hal_PWMJNI
- * Method:    getPWMConfigRaw
+ * Method:    getPWMConfigMicroseconds
  * Signature: (I)Ljava/lang/Object;
  */
 JNIEXPORT jobject JNICALL
-Java_edu_wpi_first_hal_PWMJNI_getPWMConfigRaw
+Java_edu_wpi_first_hal_PWMJNI_getPWMConfigMicroseconds
   (JNIEnv* env, jclass, jint id)
 {
   int32_t status = 0;
@@ -108,8 +92,8 @@
   int32_t centerPwm = 0;
   int32_t deadbandMinPwm = 0;
   int32_t minPwm = 0;
-  HAL_GetPWMConfigRaw((HAL_DigitalHandle)id, &maxPwm, &deadbandMaxPwm,
-                      &centerPwm, &deadbandMinPwm, &minPwm, &status);
+  HAL_GetPWMConfigMicroseconds((HAL_DigitalHandle)id, &maxPwm, &deadbandMaxPwm,
+                               &centerPwm, &deadbandMinPwm, &minPwm, &status);
   CheckStatus(env, status);
   return CreatePWMConfigDataResult(env, maxPwm, deadbandMaxPwm, centerPwm,
                                    deadbandMinPwm, minPwm);
@@ -146,15 +130,15 @@
 
 /*
  * Class:     edu_wpi_first_hal_PWMJNI
- * Method:    setPWMRaw
- * Signature: (IS)V
+ * Method:    setPulseTimeMicroseconds
+ * Signature: (II)V
  */
 JNIEXPORT void JNICALL
-Java_edu_wpi_first_hal_PWMJNI_setPWMRaw
-  (JNIEnv* env, jclass, jint id, jshort value)
+Java_edu_wpi_first_hal_PWMJNI_setPulseTimeMicroseconds
+  (JNIEnv* env, jclass, jint id, jint value)
 {
   int32_t status = 0;
-  HAL_SetPWMRaw((HAL_DigitalHandle)id, value, &status);
+  HAL_SetPWMPulseTimeMicroseconds((HAL_DigitalHandle)id, value, &status);
   CheckStatus(env, status);
 }
 
@@ -188,15 +172,16 @@
 
 /*
  * Class:     edu_wpi_first_hal_PWMJNI
- * Method:    getPWMRaw
- * Signature: (I)S
+ * Method:    getPulseTimeMicroseconds
+ * Signature: (I)I
  */
-JNIEXPORT jshort JNICALL
-Java_edu_wpi_first_hal_PWMJNI_getPWMRaw
+JNIEXPORT jint JNICALL
+Java_edu_wpi_first_hal_PWMJNI_getPulseTimeMicroseconds
   (JNIEnv* env, jclass, jint id)
 {
   int32_t status = 0;
-  jshort returnValue = HAL_GetPWMRaw((HAL_DigitalHandle)id, &status);
+  int32_t returnValue =
+      HAL_GetPWMPulseTimeMicroseconds((HAL_DigitalHandle)id, &status);
   CheckStatus(env, status);
   return returnValue;
 }
@@ -261,6 +246,20 @@
 
 /*
  * Class:     edu_wpi_first_hal_PWMJNI
+ * Method:    setAlwaysHighMode
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_hal_PWMJNI_setAlwaysHighMode
+  (JNIEnv* env, jclass, jint id)
+{
+  int32_t status = 0;
+  HAL_SetPWMAlwaysHighMode((HAL_DigitalHandle)id, &status);
+  CheckStatus(env, status);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_PWMJNI
  * Method:    setPWMPeriodScale
  * Signature: (II)V
  */
diff --git a/hal/src/main/native/cpp/jni/PowerJNI.cpp b/hal/src/main/native/cpp/jni/PowerJNI.cpp
index 92b174d..2096205 100644
--- a/hal/src/main/native/cpp/jni/PowerJNI.cpp
+++ b/hal/src/main/native/cpp/jni/PowerJNI.cpp
@@ -74,6 +74,20 @@
 
 /*
  * Class:     edu_wpi_first_hal_PowerJNI
+ * Method:    setUserEnabled6V
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_hal_PowerJNI_setUserEnabled6V
+  (JNIEnv* env, jclass, jboolean enabled)
+{
+  int32_t status = 0;
+  HAL_SetUserRailEnabled6V(enabled, &status);
+  CheckStatus(env, status);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_PowerJNI
  * Method:    getUserActive6V
  * Signature: ()Z
  */
@@ -134,6 +148,20 @@
 
 /*
  * Class:     edu_wpi_first_hal_PowerJNI
+ * Method:    setUserEnabled5V
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_hal_PowerJNI_setUserEnabled5V
+  (JNIEnv* env, jclass, jboolean enabled)
+{
+  int32_t status = 0;
+  HAL_SetUserRailEnabled5V(enabled, &status);
+  CheckStatus(env, status);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_PowerJNI
  * Method:    getUserActive5V
  * Signature: ()Z
  */
@@ -194,6 +222,20 @@
 
 /*
  * Class:     edu_wpi_first_hal_PowerJNI
+ * Method:    setUserEnabled3V3
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_hal_PowerJNI_setUserEnabled3V3
+  (JNIEnv* env, jclass, jboolean enabled)
+{
+  int32_t status = 0;
+  HAL_SetUserRailEnabled3V3(enabled, &status);
+  CheckStatus(env, status);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_PowerJNI
  * Method:    getUserActive3V3
  * Signature: ()Z
  */
@@ -251,4 +293,19 @@
   return val;
 }
 
+/*
+ * Class:     edu_wpi_first_hal_PowerJNI
+ * Method:    getCPUTemp
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL
+Java_edu_wpi_first_hal_PowerJNI_getCPUTemp
+  (JNIEnv* env, jclass)
+{
+  int32_t status = 0;
+  double val = HAL_GetCPUTemp(&status);
+  CheckStatus(env, status);
+  return val;
+}
+
 }  // extern "C"
diff --git a/hal/src/main/native/cpp/jni/SPIJNI.cpp b/hal/src/main/native/cpp/jni/SPIJNI.cpp
index 4f1e556..f8c5f7e 100644
--- a/hal/src/main/native/cpp/jni/SPIJNI.cpp
+++ b/hal/src/main/native/cpp/jni/SPIJNI.cpp
@@ -94,7 +94,7 @@
   jint retVal =
       HAL_TransactionSPI(static_cast<HAL_SPIPort>(port),
                          reinterpret_cast<const uint8_t*>(
-                             JByteArrayRef(env, dataToSend).array().data()),
+                             JSpan<const jbyte>(env, dataToSend).data()),
                          recvBuf.data(), size);
   env->SetByteArrayRegion(dataReceived, 0, size,
                           reinterpret_cast<const jbyte*>(recvBuf.data()));
@@ -131,7 +131,7 @@
 {
   jint retVal = HAL_WriteSPI(static_cast<HAL_SPIPort>(port),
                              reinterpret_cast<const uint8_t*>(
-                                 JByteArrayRef(env, dataToSend).array().data()),
+                                 JSpan<const jbyte>(env, dataToSend).data()),
                              size);
   return retVal;
 }
@@ -356,12 +356,11 @@
 Java_edu_wpi_first_hal_SPIJNI_spiSetAutoTransmitData
   (JNIEnv* env, jclass, jint port, jbyteArray dataToSend, jint zeroSize)
 {
-  JByteArrayRef jarr(env, dataToSend);
+  JSpan<const jbyte> jarr(env, dataToSend);
   int32_t status = 0;
-  HAL_SetSPIAutoTransmitData(
-      static_cast<HAL_SPIPort>(port),
-      reinterpret_cast<const uint8_t*>(jarr.array().data()),
-      jarr.array().size(), zeroSize, &status);
+  HAL_SetSPIAutoTransmitData(static_cast<HAL_SPIPort>(port),
+                             reinterpret_cast<const uint8_t*>(jarr.data()),
+                             jarr.size(), zeroSize, &status);
   CheckStatus(env, status);
 }
 
diff --git a/hal/src/main/native/cpp/jni/SerialPortJNI.cpp b/hal/src/main/native/cpp/jni/SerialPortJNI.cpp
index e7f81aa..281e8ef 100644
--- a/hal/src/main/native/cpp/jni/SerialPortJNI.cpp
+++ b/hal/src/main/native/cpp/jni/SerialPortJNI.cpp
@@ -261,11 +261,10 @@
   (JNIEnv* env, jclass, jint handle, jbyteArray dataToSend, jint size)
 {
   int32_t status = 0;
-  jint retVal =
-      HAL_WriteSerial(static_cast<HAL_SerialPortHandle>(handle),
-                      reinterpret_cast<const char*>(
-                          JByteArrayRef(env, dataToSend).array().data()),
-                      size, &status);
+  jint retVal = HAL_WriteSerial(
+      static_cast<HAL_SerialPortHandle>(handle),
+      reinterpret_cast<const char*>(JSpan<const jbyte>(env, dataToSend).data()),
+      size, &status);
   CheckStatus(env, status);
   return retVal;
 }
diff --git a/hal/src/main/native/cpp/jni/SimDeviceJNI.cpp b/hal/src/main/native/cpp/jni/SimDeviceJNI.cpp
index f681e71..2cb6c9c 100644
--- a/hal/src/main/native/cpp/jni/SimDeviceJNI.cpp
+++ b/hal/src/main/native/cpp/jni/SimDeviceJNI.cpp
@@ -65,6 +65,18 @@
 
 /*
  * Class:     edu_wpi_first_hal_SimDeviceJNI
+ * Method:    getSimDeviceName
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_edu_wpi_first_hal_SimDeviceJNI_getSimDeviceName
+  (JNIEnv* env, jclass, jint handle)
+{
+  return MakeJString(env, HAL_GetSimDeviceName(handle));
+}
+
+/*
+ * Class:     edu_wpi_first_hal_SimDeviceJNI
  * Method:    createSimValueNative
  * Signature: (ILjava/lang/String;IIJD)I
  */
@@ -138,7 +150,7 @@
   }
   return HAL_CreateSimValueEnumDouble(
       device, JStringRef{env, name}.c_str(), direction, len, carr.data(),
-      JDoubleArrayRef{env, optionValues}.array().data(), initialValue);
+      JSpan<const jdouble>{env, optionValues}.data(), initialValue);
 }
 
 /*
diff --git a/hal/src/main/native/cpp/jni/simulation/AddressableLEDDataJNI.cpp b/hal/src/main/native/cpp/jni/simulation/AddressableLEDDataJNI.cpp
index 70b31ab..38d9ce7 100644
--- a/hal/src/main/native/cpp/jni/simulation/AddressableLEDDataJNI.cpp
+++ b/hal/src/main/native/cpp/jni/simulation/AddressableLEDDataJNI.cpp
@@ -269,7 +269,7 @@
 Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_setData
   (JNIEnv* env, jclass, jint index, jbyteArray arr)
 {
-  JByteArrayRef jArrRef{env, arr};
+  JSpan<const jbyte> jArrRef{env, arr};
   auto arrRef = jArrRef.array();
   HALSIM_SetAddressableLEDData(
       index, reinterpret_cast<const HAL_AddressableLEDData*>(arrRef.data()),
diff --git a/hal/src/main/native/cpp/jni/simulation/DriverStationDataJNI.cpp b/hal/src/main/native/cpp/jni/simulation/DriverStationDataJNI.cpp
index c50b8e3..8b1ba4f 100644
--- a/hal/src/main/native/cpp/jni/simulation/DriverStationDataJNI.cpp
+++ b/hal/src/main/native/cpp/jni/simulation/DriverStationDataJNI.cpp
@@ -4,8 +4,7 @@
 
 #include <jni.h>
 
-#include <cstring>
-
+#include <wpi/StringExtras.h>
 #include <wpi/jni_util.h>
 
 #include "CallbackStore.h"
@@ -436,7 +435,7 @@
 {
   HAL_JoystickAxes axes;
   {
-    wpi::java::JFloatArrayRef jArrayRef(env, axesArray);
+    JSpan<const jfloat> jArrayRef(env, axesArray);
     auto arrayRef = jArrayRef.array();
     auto arraySize = arrayRef.size();
     int maxCount =
@@ -461,7 +460,7 @@
 {
   HAL_JoystickPOVs povs;
   {
-    wpi::java::JShortArrayRef jArrayRef(env, povsArray);
+    JSpan<const jshort> jArrayRef(env, povsArray);
     auto arrayRef = jArrayRef.array();
     auto arraySize = arrayRef.size();
     int maxCount =
@@ -539,11 +538,12 @@
   JStringRef gameSpecificMessageRef{env, gameSpecificMessage};
 
   HAL_MatchInfo halMatchInfo;
-  std::snprintf(halMatchInfo.eventName, sizeof(halMatchInfo.eventName), "%s",
-                eventNameRef.c_str());
-  std::snprintf(reinterpret_cast<char*>(halMatchInfo.gameSpecificMessage),
-                sizeof(halMatchInfo.gameSpecificMessage), "%s",
-                gameSpecificMessageRef.c_str());
+  wpi::format_to_n_c_str(halMatchInfo.eventName, sizeof(halMatchInfo.eventName),
+                         "{}", eventNameRef.str());
+  wpi::format_to_n_c_str(
+      reinterpret_cast<char*>(halMatchInfo.gameSpecificMessage),
+      sizeof(halMatchInfo.gameSpecificMessage), "{}",
+      gameSpecificMessageRef.str());
   halMatchInfo.gameSpecificMessageSize = gameSpecificMessageRef.size();
   halMatchInfo.matchType = (HAL_MatchType)matchType;
   halMatchInfo.matchNumber = matchNumber;
diff --git a/hal/src/main/native/cpp/jni/simulation/EncoderDataJNI.cpp b/hal/src/main/native/cpp/jni/simulation/EncoderDataJNI.cpp
index 69549a1..a33458f 100644
--- a/hal/src/main/native/cpp/jni/simulation/EncoderDataJNI.cpp
+++ b/hal/src/main/native/cpp/jni/simulation/EncoderDataJNI.cpp
@@ -414,6 +414,56 @@
 
 /*
  * Class:     edu_wpi_first_hal_simulation_EncoderDataJNI
+ * Method:    registerDistancePerPulseCallback
+ * Signature: (ILjava/lang/Object;Z)I
+ */
+JNIEXPORT jint JNICALL
+Java_edu_wpi_first_hal_simulation_EncoderDataJNI_registerDistancePerPulseCallback
+  (JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
+{
+  return sim::AllocateCallback(env, index, callback, initialNotify,
+                               &HALSIM_RegisterEncoderDistancePerPulseCallback);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_simulation_EncoderDataJNI
+ * Method:    cancelDistancePerPulseCallback
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_hal_simulation_EncoderDataJNI_cancelDistancePerPulseCallback
+  (JNIEnv* env, jclass, jint index, jint handle)
+{
+  return sim::FreeCallback(env, handle, index,
+                           &HALSIM_CancelEncoderDistancePerPulseCallback);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_simulation_EncoderDataJNI
+ * Method:    getDistancePerPulse
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL
+Java_edu_wpi_first_hal_simulation_EncoderDataJNI_getDistancePerPulse
+  (JNIEnv*, jclass, jint index)
+{
+  return HALSIM_GetEncoderDistancePerPulse(index);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_simulation_EncoderDataJNI
+ * Method:    setDistancePerPulse
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_hal_simulation_EncoderDataJNI_setDistancePerPulse
+  (JNIEnv*, jclass, jint index, jdouble value)
+{
+  HALSIM_SetEncoderDistancePerPulse(index, value);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_simulation_EncoderDataJNI
  * Method:    setDistance
  * Signature: (ID)V
  */
diff --git a/hal/src/main/native/cpp/jni/simulation/PWMDataJNI.cpp b/hal/src/main/native/cpp/jni/simulation/PWMDataJNI.cpp
index 31c79a7..ea52728 100644
--- a/hal/src/main/native/cpp/jni/simulation/PWMDataJNI.cpp
+++ b/hal/src/main/native/cpp/jni/simulation/PWMDataJNI.cpp
@@ -64,52 +64,52 @@
 
 /*
  * Class:     edu_wpi_first_hal_simulation_PWMDataJNI
- * Method:    registerRawValueCallback
+ * Method:    registerPulseMicrosecondCallback
  * Signature: (ILjava/lang/Object;Z)I
  */
 JNIEXPORT jint JNICALL
-Java_edu_wpi_first_hal_simulation_PWMDataJNI_registerRawValueCallback
+Java_edu_wpi_first_hal_simulation_PWMDataJNI_registerPulseMicrosecondCallback
   (JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
 {
   return sim::AllocateCallback(env, index, callback, initialNotify,
-                               &HALSIM_RegisterPWMRawValueCallback);
+                               &HALSIM_RegisterPWMPulseMicrosecondCallback);
 }
 
 /*
  * Class:     edu_wpi_first_hal_simulation_PWMDataJNI
- * Method:    cancelRawValueCallback
+ * Method:    cancelPulseMicrosecondCallback
  * Signature: (II)V
  */
 JNIEXPORT void JNICALL
-Java_edu_wpi_first_hal_simulation_PWMDataJNI_cancelRawValueCallback
+Java_edu_wpi_first_hal_simulation_PWMDataJNI_cancelPulseMicrosecondCallback
   (JNIEnv* env, jclass, jint index, jint handle)
 {
   return sim::FreeCallback(env, handle, index,
-                           &HALSIM_CancelPWMRawValueCallback);
+                           &HALSIM_CancelPWMPulseMicrosecondCallback);
 }
 
 /*
  * Class:     edu_wpi_first_hal_simulation_PWMDataJNI
- * Method:    getRawValue
+ * Method:    getPulseMicrosecond
  * Signature: (I)I
  */
 JNIEXPORT jint JNICALL
-Java_edu_wpi_first_hal_simulation_PWMDataJNI_getRawValue
+Java_edu_wpi_first_hal_simulation_PWMDataJNI_getPulseMicrosecond
   (JNIEnv*, jclass, jint index)
 {
-  return HALSIM_GetPWMRawValue(index);
+  return HALSIM_GetPWMPulseMicrosecond(index);
 }
 
 /*
  * Class:     edu_wpi_first_hal_simulation_PWMDataJNI
- * Method:    setRawValue
+ * Method:    setPulseMicrosecond
  * Signature: (II)V
  */
 JNIEXPORT void JNICALL
-Java_edu_wpi_first_hal_simulation_PWMDataJNI_setRawValue
+Java_edu_wpi_first_hal_simulation_PWMDataJNI_setPulseMicrosecond
   (JNIEnv*, jclass, jint index, jint value)
 {
-  HALSIM_SetPWMRawValue(index, value);
+  HALSIM_SetPWMPulseMicrosecond(index, value);
 }
 
 /*
diff --git a/hal/src/main/native/cpp/jni/simulation/RoboRioDataJNI.cpp b/hal/src/main/native/cpp/jni/simulation/RoboRioDataJNI.cpp
index 5bcd114..9555f59 100644
--- a/hal/src/main/native/cpp/jni/simulation/RoboRioDataJNI.cpp
+++ b/hal/src/main/native/cpp/jni/simulation/RoboRioDataJNI.cpp
@@ -830,6 +830,106 @@
 
 /*
  * Class:     edu_wpi_first_hal_simulation_RoboRioDataJNI
+ * Method:    registerCPUTempCallback
+ * Signature: (Ljava/lang/Object;Z)I
+ */
+JNIEXPORT jint JNICALL
+Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_registerCPUTempCallback
+  (JNIEnv* env, jclass, jobject callback, jboolean initialNotify)
+{
+  return sim::AllocateCallbackNoIndex(env, callback, initialNotify,
+                                      &HALSIM_RegisterRoboRioCPUTempCallback);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_simulation_RoboRioDataJNI
+ * Method:    cancelCPUTempCallback
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_cancelCPUTempCallback
+  (JNIEnv* env, jclass, jint handle)
+{
+  return sim::FreeCallbackNoIndex(env, handle,
+                                  &HALSIM_CancelRoboRioCPUTempCallback);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_simulation_RoboRioDataJNI
+ * Method:    getCPUTemp
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL
+Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_getCPUTemp
+  (JNIEnv*, jclass)
+{
+  return HALSIM_GetRoboRioCPUTemp();
+}
+
+/*
+ * Class:     edu_wpi_first_hal_simulation_RoboRioDataJNI
+ * Method:    setCPUTemp
+ * Signature: (D)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_setCPUTemp
+  (JNIEnv*, jclass, jdouble cpuTemp)
+{
+  HALSIM_SetRoboRioCPUTemp(cpuTemp);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_simulation_RoboRioDataJNI
+ * Method:    registerTeamNumberCallback
+ * Signature: (Ljava/lang/Object;Z)I
+ */
+JNIEXPORT jint JNICALL
+Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_registerTeamNumberCallback
+  (JNIEnv* env, jclass, jobject callback, jboolean initialNotify)
+{
+  return sim::AllocateCallbackNoIndex(
+      env, callback, initialNotify, &HALSIM_RegisterRoboRioTeamNumberCallback);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_simulation_RoboRioDataJNI
+ * Method:    cancelTeamNumberCallback
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_cancelTeamNumberCallback
+  (JNIEnv* env, jclass, jint handle)
+{
+  return sim::FreeCallbackNoIndex(env, handle,
+                                  &HALSIM_CancelRoboRioTeamNumberCallback);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_simulation_RoboRioDataJNI
+ * Method:    getTeamNumber
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL
+Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_getTeamNumber
+  (JNIEnv*, jclass)
+{
+  return HALSIM_GetRoboRioTeamNumber();
+}
+
+/*
+ * Class:     edu_wpi_first_hal_simulation_RoboRioDataJNI
+ * Method:    setTeamNumber
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_setTeamNumber
+  (JNIEnv*, jclass, jint value)
+{
+  HALSIM_SetRoboRioTeamNumber(value);
+}
+
+/*
+ * Class:     edu_wpi_first_hal_simulation_RoboRioDataJNI
  * Method:    getSerialNumber
  * Signature: ()Ljava/lang/String;
  */
diff --git a/hal/src/main/native/cpp/jni/simulation/SimDeviceDataJNI.cpp b/hal/src/main/native/cpp/jni/simulation/SimDeviceDataJNI.cpp
index c7c2a19..98dab72 100644
--- a/hal/src/main/native/cpp/jni/simulation/SimDeviceDataJNI.cpp
+++ b/hal/src/main/native/cpp/jni/simulation/SimDeviceDataJNI.cpp
@@ -468,7 +468,11 @@
 Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_getSimDeviceName
   (JNIEnv* env, jclass, jint handle)
 {
-  return MakeJString(env, HALSIM_GetSimDeviceName(handle));
+  const char* name = HALSIM_GetSimDeviceName(handle);
+  if (!name) {
+    return nullptr;
+  }
+  return MakeJString(env, name);
 }
 
 /*
diff --git a/hal/src/main/native/include/hal/AddressableLED.h b/hal/src/main/native/include/hal/AddressableLED.h
index 7674979..1fba59c 100644
--- a/hal/src/main/native/include/hal/AddressableLED.h
+++ b/hal/src/main/native/include/hal/AddressableLED.h
@@ -19,36 +19,112 @@
 extern "C" {
 #endif
 
+/**
+ * Initialize Addressable LED using a PWM Digital handle.
+ *
+ * @param[in] outputPort handle of the digital port for PWM
+ * @param[out] status the error code, or 0 for success
+ * @return Addressable LED handle
+ */
 HAL_AddressableLEDHandle HAL_InitializeAddressableLED(
     HAL_DigitalHandle outputPort, int32_t* status);
 
+/**
+ * Free the Addressable LED Handle.
+ *
+ * @param[in] handle the Addressable LED handle to free
+ */
 void HAL_FreeAddressableLED(HAL_AddressableLEDHandle handle);
 
+/**
+ * Set the Addressable LED PWM Digital port.
+ *
+ * @param[in] handle the Addressable LED handle
+ * @param[in] outputPort The digital handle of the PWM port
+ * @param[out] status the error code, or 0 for success
+ */
 void HAL_SetAddressableLEDOutputPort(HAL_AddressableLEDHandle handle,
                                      HAL_DigitalHandle outputPort,
                                      int32_t* status);
 
+/**
+ * Sets the length of the LED strip.
+ *
+ * <p>The max length is 5460 LEDs.
+ *
+ * @param[in] handle the Addressable LED handle
+ * @param[in] length the strip length
+ * @param[out] status the error code, or 0 for success
+ */
 void HAL_SetAddressableLEDLength(HAL_AddressableLEDHandle handle,
                                  int32_t length, int32_t* status);
 
+/**
+ * Sets the led output data.
+ *
+ * <p>If the output is enabled, this will start writing the next data cycle.
+ * It is safe to call, even while output is enabled.
+ *
+ * @param[in] handle the Addressable LED handle
+ * @param[in] data the buffer to write
+ * @param[in] length the strip length
+ * @param[out] status the error code, or 0 for success
+ */
 void HAL_WriteAddressableLEDData(HAL_AddressableLEDHandle handle,
                                  const struct HAL_AddressableLEDData* data,
                                  int32_t length, int32_t* status);
 
+/**
+ * Sets the bit timing.
+ *
+ * <p>By default, the driver is set up to drive WS2812Bs, so nothing needs to
+ * be set for those.
+ *
+ * @param[in] handle the Addressable LED handle
+ * @param[in] highTime0NanoSeconds high time for 0 bit (default 400ns)
+ * @param[in] lowTime0NanoSeconds low time for 0 bit (default 900ns)
+ * @param[in] highTime1NanoSeconds high time for 1 bit (default 900ns)
+ * @param[in] lowTime1NanoSeconds low time for 1 bit (default 600ns)
+ * @param[out] status the error code, or 0 for success
+ */
 void HAL_SetAddressableLEDBitTiming(HAL_AddressableLEDHandle handle,
-                                    int32_t lowTime0NanoSeconds,
                                     int32_t highTime0NanoSeconds,
-                                    int32_t lowTime1NanoSeconds,
+                                    int32_t lowTime0NanoSeconds,
                                     int32_t highTime1NanoSeconds,
+                                    int32_t lowTime1NanoSeconds,
                                     int32_t* status);
 
+/**
+ * Sets the sync time.
+ *
+ * <p>The sync time is the time to hold output so LEDs enable. Default set for
+ * WS2812B.
+ *
+ * @param[in] handle the Addressable LED handle
+ * @param[in] syncTimeMicroSeconds the sync time (default 280us)
+ * @param[out] status the error code, or 0 for success
+ */
 void HAL_SetAddressableLEDSyncTime(HAL_AddressableLEDHandle handle,
                                    int32_t syncTimeMicroSeconds,
                                    int32_t* status);
 
+/**
+ * Starts the output.
+ *
+ * <p>The output writes continuously.
+ *
+ * @param[in] handle the Addressable LED handle
+ * @param[out] status the error code, or 0 for success
+ */
 void HAL_StartAddressableLEDOutput(HAL_AddressableLEDHandle handle,
                                    int32_t* status);
 
+/**
+ * Stops the output.
+ *
+ * @param[in] handle the Addressable LED handle
+ * @param[out] status the error code, or 0 for success
+ */
 void HAL_StopAddressableLEDOutput(HAL_AddressableLEDHandle handle,
                                   int32_t* status);
 
diff --git a/hal/src/main/native/include/hal/AddressableLEDTypes.h b/hal/src/main/native/include/hal/AddressableLEDTypes.h
index dbaa776..48918f4 100644
--- a/hal/src/main/native/include/hal/AddressableLEDTypes.h
+++ b/hal/src/main/native/include/hal/AddressableLEDTypes.h
@@ -6,11 +6,13 @@
 
 #include <stdint.h>
 
+/** max length of LED strip supported by FPGA. */
 #define HAL_kAddressableLEDMaxLength 5460
 
+/** structure for holding one LED's color data. */
 struct HAL_AddressableLEDData {
-  uint8_t b;
-  uint8_t g;
-  uint8_t r;
+  uint8_t b;  ///< blue value
+  uint8_t g;  ///< green value
+  uint8_t r;  ///< red value
   uint8_t padding;
 };
diff --git a/hal/src/main/native/include/hal/AnalogGyro.h b/hal/src/main/native/include/hal/AnalogGyro.h
index ed7c308..6dd948a 100644
--- a/hal/src/main/native/include/hal/AnalogGyro.h
+++ b/hal/src/main/native/include/hal/AnalogGyro.h
@@ -21,7 +21,7 @@
 /**
  * Initializes an analog gyro.
  *
- * @param[in] handle handle to the analog port
+ * @param[in] handle handle to the analog input port
  * @param[in] allocationLocation the location where the allocation is occurring
  *                                (can be null)
  * @param[out] status the error code, or 0 for success
@@ -43,7 +43,7 @@
 /**
  * Frees an analog gyro.
  *
- * @param handle the gyro handle
+ * @param[in,out] handle the gyro handle
  */
 void HAL_FreeAnalogGyro(HAL_GyroHandle handle);
 
diff --git a/hal/src/main/native/include/hal/AnalogInput.h b/hal/src/main/native/include/hal/AnalogInput.h
index 0a1a3c5..462103a 100644
--- a/hal/src/main/native/include/hal/AnalogInput.h
+++ b/hal/src/main/native/include/hal/AnalogInput.h
@@ -33,14 +33,14 @@
 /**
  * Frees an analog input port.
  *
- * @param analogPortHandle Handle to the analog port.
+ * @param[in,out] analogPortHandle Handle to the analog port.
  */
 void HAL_FreeAnalogInputPort(HAL_AnalogInputHandle analogPortHandle);
 
 /**
  * Checks that the analog module number is valid.
  *
- * @param module The analog module number.
+ * @param[in] module The analog module number.
  * @return Analog module is valid and present
  */
 HAL_Bool HAL_CheckAnalogModule(int32_t module);
@@ -50,7 +50,7 @@
  * Verifies that the analog channel number is one of the legal channel numbers.
  * Channel numbers are 0-based.
  *
- * @param channel The analog output channel number.
+ * @param[in] channel The analog output channel number.
  * @return Analog channel is valid
  */
 HAL_Bool HAL_CheckAnalogInputChannel(int32_t channel);
@@ -162,9 +162,9 @@
  * The sample is 12-bit + the value 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**(OversamplBits + AverageBits) samples have been acquired from
- * the module on this channel. Use GetAverageVoltage() to get the analog value
- * in calibrated units.
+ * 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.
  *
  * @param[in] analogPortHandle Handle to the analog port to use.
  * @param[out] status the error code, or 0 for success
diff --git a/hal/src/main/native/include/hal/AnalogTrigger.h b/hal/src/main/native/include/hal/AnalogTrigger.h
index 72727a8..f4622e3 100644
--- a/hal/src/main/native/include/hal/AnalogTrigger.h
+++ b/hal/src/main/native/include/hal/AnalogTrigger.h
@@ -45,6 +45,7 @@
  *
  * @param[in] dutyCycleHandle the analog input to use for duty cycle
  * @param[out] status          Error status variable. 0 on success.
+ * @return tbe created analog trigger handle
  */
 HAL_AnalogTriggerHandle HAL_InitializeAnalogTriggerDutyCycle(
     HAL_DutyCycleHandle dutyCycleHandle, int32_t* status);
diff --git a/hal/src/main/native/include/hal/CANAPI.h b/hal/src/main/native/include/hal/CANAPI.h
index d5244b5..f515d60 100644
--- a/hal/src/main/native/include/hal/CANAPI.h
+++ b/hal/src/main/native/include/hal/CANAPI.h
@@ -20,6 +20,15 @@
 #endif
 
 /**
+ * Reads the current value of the millisecond-resolution timer that the CAN API
+ * functions use as a time base.
+ *
+ * @return Current value of timer used as a base time by the CAN API in
+ * milliseconds.
+ */
+uint32_t HAL_GetCANPacketBaseTime(void);
+
+/**
  * Initializes a CAN device.
  *
  * These follow the FIRST standard CAN layout.
@@ -38,7 +47,7 @@
 /**
  * Frees a CAN device
  *
- * @param handle the CAN handle
+ * @param[in,out] handle the CAN handle
  */
 void HAL_CleanCAN(HAL_CANHandle handle);
 
@@ -111,8 +120,8 @@
  * @param[in] apiId              the ID to read (0-1023)
  * @param[out] data              the packet data (8 bytes)
  * @param[out] length            the received length (0-8 bytes)
- * @param[out] receivedTimestamp the packet received timestamp (based off of
- *                               CLOCK_MONOTONIC)
+ * @param[out] receivedTimestamp the packet received timestamp in ms (based off
+ *                               of CLOCK_MONOTONIC)
  * @param[out] status            Error status variable. 0 on success.
  */
 void HAL_ReadCANPacketNew(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
@@ -127,8 +136,8 @@
  * @param[in] apiId              the ID to read (0-1023)
  * @param[out] data              the packet data (8 bytes)
  * @param[out] length            the received length (0-8 bytes)
- * @param[out] receivedTimestamp the packet received timestamp (based off of
- *                               CLOCK_MONOTONIC)
+ * @param[out] receivedTimestamp the packet received timestamp in ms (based off
+ *                               of CLOCK_MONOTONIC)
  * @param[out] status            Error status variable. 0 on success.
  */
 void HAL_ReadCANPacketLatest(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
@@ -144,8 +153,8 @@
  * @param[in] apiId              the ID to read (0-1023)
  * @param[out] data              the packet data (8 bytes)
  * @param[out] length            the received length (0-8 bytes)
- * @param[out] receivedTimestamp the packet received timestamp (based off of
- *                               CLOCK_MONOTONIC)
+ * @param[out] receivedTimestamp the packet received timestamp in ms (based off
+ *                               of CLOCK_MONOTONIC)
  * @param[out] timeoutMs         the timeout time for the packet
  * @param[out] status            Error status variable. 0 on success.
  */
diff --git a/hal/src/main/native/include/hal/CANAPITypes.h b/hal/src/main/native/include/hal/CANAPITypes.h
index 404eecf..decaf86 100644
--- a/hal/src/main/native/include/hal/CANAPITypes.h
+++ b/hal/src/main/native/include/hal/CANAPITypes.h
@@ -55,7 +55,10 @@
   HAL_CAN_Man_kCopperforge = 10,
   HAL_CAN_Man_kPWF = 11,
   HAL_CAN_Man_kStudica = 12,
-  HAL_CAN_Man_kTheThriftyBot = 13
+  HAL_CAN_Man_kTheThriftyBot = 13,
+  HAL_CAN_Man_kReduxRobotics = 14,
+  HAL_CAN_Man_kAndyMark = 15,
+  HAL_CAN_Man_kVividHosting = 16
 };
 // clang-format on
 /** @} */
diff --git a/hal/src/main/native/include/hal/CTREPCM.h b/hal/src/main/native/include/hal/CTREPCM.h
index 1bed928..932ed34 100644
--- a/hal/src/main/native/include/hal/CTREPCM.h
+++ b/hal/src/main/native/include/hal/CTREPCM.h
@@ -9,7 +9,7 @@
 #include "hal/Types.h"
 
 /**
- * @defgroup hal_ctre_pcm CTRE PCM Functions
+ * @defgroup hal_ctre_pcm CTRE Pneumatic Control Module (PCM) Functions
  * @ingroup hal_capi
  * @{
  */
@@ -18,51 +18,241 @@
 extern "C" {
 #endif
 
+/**
+ * Initializes a PCM.
+ *
+ * @param[in] module             the CAN ID to initialize
+ * @param[in] allocationLocation the location where the allocation is occurring
+ *                               (can be null)
+ * @param[out] status            Error status variable. 0 on success.
+ * @return the created PH handle
+ */
 HAL_CTREPCMHandle HAL_InitializeCTREPCM(int32_t module,
                                         const char* allocationLocation,
                                         int32_t* status);
+
+/**
+ * Frees a PCM handle.
+ *
+ * @param[in] handle the PCMhandle
+ */
 void HAL_FreeCTREPCM(HAL_CTREPCMHandle handle);
 
+/**
+ * Checks if a solenoid channel number is valid.
+ *
+ * @param[in] channel the channel to check
+ * @return true if the channel is valid, otherwise false
+ */
 HAL_Bool HAL_CheckCTREPCMSolenoidChannel(int32_t channel);
 
+/**
+ * Get whether compressor is turned on.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return true if the compressor is turned on
+ */
 HAL_Bool HAL_GetCTREPCMCompressor(HAL_CTREPCMHandle handle, int32_t* status);
+
+/**
+ * Enables the compressor closed loop control using the digital pressure switch.
+ * The compressor will turn on when the pressure switch indicates that the
+ * system is not full, and will turn off when the pressure switch indicates that
+ * the system is full.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[in] enabled true to enable closed loop control
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_SetCTREPCMClosedLoopControl(HAL_CTREPCMHandle handle, HAL_Bool enabled,
                                      int32_t* status);
+
+/**
+ * Get whether the PCM closed loop control is enabled.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return True if closed loop control is enabled, otherwise false.
+ */
 HAL_Bool HAL_GetCTREPCMClosedLoopControl(HAL_CTREPCMHandle handle,
                                          int32_t* status);
+
+/**
+ * Returns the state of the pressure switch.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return True if pressure switch indicates that the system is full,
+ * otherwise false.
+ */
 HAL_Bool HAL_GetCTREPCMPressureSwitch(HAL_CTREPCMHandle handle,
                                       int32_t* status);
+
+/**
+ * Returns the current drawn by the compressor.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return The current drawn by the compressor in amps.
+ */
 double HAL_GetCTREPCMCompressorCurrent(HAL_CTREPCMHandle handle,
                                        int32_t* status);
 
+/**
+ * Return whether the compressor current is currently too high.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return True if the compressor current is too high, otherwise false.
+ * @see HAL_GetCTREPCMCompressorShortedStickyFault
+ */
 HAL_Bool HAL_GetCTREPCMCompressorCurrentTooHighFault(HAL_CTREPCMHandle handle,
                                                      int32_t* status);
+
+/**
+ * Returns whether the compressor current has been too high since sticky
+ * faults were last cleared. This fault is persistent and can be cleared by
+ * HAL_ClearAllCTREPCMStickyFaults()
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return True if the compressor current has been too high since sticky
+ * faults were last cleared.
+ * @see HAL_GetCTREPCMCompressorCurrentTooHighFault()
+ */
 HAL_Bool HAL_GetCTREPCMCompressorCurrentTooHighStickyFault(
     HAL_CTREPCMHandle handle, int32_t* status);
+
+/**
+ * Returns whether the compressor has been shorted since sticky faults were
+ * last cleared. This fault is persistent and can be cleared by
+ * HAL_ClearAllCTREPCMStickyFaults()
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return True if the compressor has been shorted since sticky faults were
+ * last cleared, otherwise false.
+ * @see HAL_GetCTREPCMCompressorShortedFault()
+ */
 HAL_Bool HAL_GetCTREPCMCompressorShortedStickyFault(HAL_CTREPCMHandle handle,
                                                     int32_t* status);
+
+/**
+ * Returns whether the compressor is currently shorted.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return True if the compressor is currently shorted, otherwise false.
+ * @see HAL_GetCTREPCMCompressorShortedStickyFault
+ */
 HAL_Bool HAL_GetCTREPCMCompressorShortedFault(HAL_CTREPCMHandle handle,
                                               int32_t* status);
+
+/**
+ * Returns whether the compressor has been disconnected since sticky faults
+ * were last cleared. This fault is persistent and can be cleared by
+ * HAL_ClearAllCTREPCMStickyFaults()
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return True if the compressor has been disconnected since sticky faults
+ * were last cleared, otherwise false.
+ * @see HAL_GetCTREPCMCompressorShortedFault()
+ */
 HAL_Bool HAL_GetCTREPCMCompressorNotConnectedStickyFault(
     HAL_CTREPCMHandle handle, int32_t* status);
+
+/**
+ * Returns whether the compressor is currently disconnected.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return True if compressor is currently disconnected, otherwise false.
+ * @see HAL_GetCTREPCMCompressorNotConnectedStickyFault()
+ */
 HAL_Bool HAL_GetCTREPCMCompressorNotConnectedFault(HAL_CTREPCMHandle handle,
                                                    int32_t* status);
 
+/**
+ * Gets a bitmask of solenoid values.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return solenoid values
+ */
 int32_t HAL_GetCTREPCMSolenoids(HAL_CTREPCMHandle handle, int32_t* status);
+
+/**
+ * Sets solenoids on a pneumatics module.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[in] mask bitmask to set
+ * @param[in] values solenoid values
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_SetCTREPCMSolenoids(HAL_CTREPCMHandle handle, int32_t mask,
                              int32_t values, int32_t* status);
 
+/**
+ * Get a bitmask of disabled solenoids.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return bitmask of disabled solenoids
+ */
 int32_t HAL_GetCTREPCMSolenoidDisabledList(HAL_CTREPCMHandle handle,
                                            int32_t* status);
+
+/**
+ * Returns whether the solenoid has reported a voltage fault since sticky faults
+ * were last cleared. This fault is persistent and can be cleared by
+ * HAL_ClearAllCTREPCMStickyFaults()
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return True if solenoid is reporting a fault, otherwise false.
+ * @see HAL_GetCTREPCMSolenoidVoltageFault()
+ */
 HAL_Bool HAL_GetCTREPCMSolenoidVoltageStickyFault(HAL_CTREPCMHandle handle,
                                                   int32_t* status);
+/**
+ * Returns whether the solenoid is currently reporting a voltage fault.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return True if solenoid is reporting a fault, otherwise false.
+ * @see HAL_GetCTREPCMSolenoidVoltageStickyFault()
+ */
 HAL_Bool HAL_GetCTREPCMSolenoidVoltageFault(HAL_CTREPCMHandle handle,
                                             int32_t* status);
 
+/**
+ * Clears all sticky faults on this device.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_ClearAllCTREPCMStickyFaults(HAL_CTREPCMHandle handle, int32_t* status);
 
+/**
+ * Fire a single solenoid shot.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[in] index solenoid index
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_FireCTREPCMOneShot(HAL_CTREPCMHandle handle, int32_t index,
                             int32_t* status);
+
+/**
+ * Set the duration for a single solenoid shot.
+ *
+ * @param[in] handle  the PCM handle
+ * @param[in] index solenoid index
+ * @param[in] durMs shot duration in ms
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_SetCTREPCMOneShotDuration(HAL_CTREPCMHandle handle, int32_t index,
                                    int32_t durMs, int32_t* status);
 
diff --git a/hal/src/main/native/include/hal/Counter.h b/hal/src/main/native/include/hal/Counter.h
index cc2d776..0338cda 100644
--- a/hal/src/main/native/include/hal/Counter.h
+++ b/hal/src/main/native/include/hal/Counter.h
@@ -233,7 +233,7 @@
  */
 int32_t HAL_GetCounter(HAL_CounterHandle counterHandle, int32_t* status);
 
-/*
+/**
  * Gets the Period of the most recent count.
  *
  * Returns the time interval of the most recent count. This can be used for
diff --git a/hal/src/main/native/include/hal/DIO.h b/hal/src/main/native/include/hal/DIO.h
index 6b922b5..f531384 100644
--- a/hal/src/main/native/include/hal/DIO.h
+++ b/hal/src/main/native/include/hal/DIO.h
@@ -37,7 +37,7 @@
  * Checks if a DIO channel is valid.
  *
  * @param channel the channel number to check
- * @return true if the channel is correct, otherwise false
+ * @return true if the channel is valid, otherwise false
  */
 HAL_Bool HAL_CheckDIOChannel(int32_t channel);
 
@@ -77,7 +77,7 @@
  *
  * The valid range is from 0.6 Hz to 19 kHz.
  *
- *  The frequency resolution is logarithmic.
+ * The frequency resolution is logarithmic.
  *
  * @param[in] rate the frequency to output all digital output PWM signals
  * @param[out] status Error status variable. 0 on success.
@@ -227,7 +227,7 @@
  *
  * Sets the filter period in FPGA cycles.  Even though there are 2 different
  * filter index domains (MXP vs HDR), ignore that distinction for now since it
- * compilicates the interface.  That can be changed later.
+ * complicates the interface.  That can be changed later.
  *
  * @param[in] filterIndex the filter index, 0 - 2
  * @param[in] value       the number of cycles that the signal must not
@@ -241,11 +241,12 @@
  *
  * Gets the filter period in FPGA cycles.  Even though there are 2 different
  * filter index domains (MXP vs HDR), ignore that distinction for now since it
- * compilicates the interface.  Set status to NiFpga_Status_SoftwareFault if the
- * filter values miss-match.
+ * complicates the interface.  Set status to NiFpga_Status_SoftwareFault if the
+ * filter values mismatch.
  *
  * @param[in] filterIndex the filter index, 0 - 2
  * @param[out] status     Error status variable. 0 on success.
+ * @return                The number of FPGA cycles of the filter period.
  */
 int64_t HAL_GetFilterPeriod(int32_t filterIndex, int32_t* status);
 #ifdef __cplusplus
diff --git a/hal/src/main/native/include/hal/DMA.h b/hal/src/main/native/include/hal/DMA.h
index 7610d9b..b735b6d 100644
--- a/hal/src/main/native/include/hal/DMA.h
+++ b/hal/src/main/native/include/hal/DMA.h
@@ -40,7 +40,7 @@
 #endif
 
 /**
- * Initializes an object for peforming DMA transfers.
+ * Initializes an object for performing DMA transfers.
  *
  * @param[out] status Error status variable. 0 on success.
  * @return the created dma handle
@@ -185,7 +185,7 @@
                                    int32_t* status);
 
 /**
- * Adds acuumulator data of an analog input to be collected by DMA.
+ * Adds accumulator data of an analog input to be collected by DMA.
  *
  * This can only be called if DMA is not started.
  *
@@ -310,7 +310,7 @@
  *                           timing out
  * @param[in] remainingOut   the number of samples remaining in the queue
  * @param[out] status        Error status variable. 0 on success.
- * @return the succes result of the sample read
+ * @return the success result of the sample read
  */
 enum HAL_DMAReadStatus HAL_ReadDMA(HAL_DMAHandle handle,
                                    HAL_DMASample* dmaSample,
diff --git a/hal/src/main/native/include/hal/DriverStation.h b/hal/src/main/native/include/hal/DriverStation.h
index ae68b65..5edacf5 100644
--- a/hal/src/main/native/include/hal/DriverStation.h
+++ b/hal/src/main/native/include/hal/DriverStation.h
@@ -28,10 +28,11 @@
  * @param errorCode the error code
  * @param isLVCode  true for a LV error code, false for a standard error code
  * @param details   the details of the error
- * @param location  the file location of the errror
+ * @param location  the file location of the error
  * @param callStack the callstack of the error
  * @param printMsg  true to print the error message to stdout as well as to the
  * DS
+ * @return the error code, or 0 for success
  */
 int32_t HAL_SendError(HAL_Bool isError, int32_t errorCode, HAL_Bool isLVCode,
                       const char* details, const char* location,
@@ -48,13 +49,14 @@
  * Sends a line to the driver station console.
  *
  * @param line the line to send (null terminated)
+ * @return the error code, or 0 for success
  */
 int32_t HAL_SendConsoleLine(const char* line);
 
 /**
  * Gets the current control word of the driver station.
  *
- * The control work contains the robot state.
+ * The control word contains the robot state.
  *
  * @param controlWord the control word (out)
  * @return the error code, or 0 for success
@@ -117,7 +119,7 @@
                                   HAL_JoystickDescriptor* desc);
 
 /**
- * Gets is a specific joystick is considered to be an XBox controller.
+ * Gets whether a specific joystick is considered to be an XBox controller.
  *
  * @param joystickNum the joystick number
  * @return true if xbox, false otherwise
@@ -179,25 +181,32 @@
                                int32_t leftRumble, int32_t rightRumble);
 
 /**
- * Returns 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).
- *
+ * 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.
+ * <p>When connected to the real field, this number only changes in full integer
+ * increments, and always counts down.
+ *
+ * <p>When the DS is in practice mode, this number is a floating point number,
+ * and counts down.
+ *
+ * <p>When the DS is in teleop or autonomous mode, this number is a floating
+ * point number, and counts up.
+ *
+ * <p>Simulation matches DS behavior without an FMS connected.
  *
  * @param[out] status the error code, or 0 for success
- * @return time remaining in current match period (auto or teleop)
+ * @return Time remaining in current match period (auto or teleop) in seconds
  */
 double HAL_GetMatchTime(int32_t* status);
 
 /**
  * Gets if outputs are enabled by the control system.
+ *
+ * @return true if outputs are enabled
  */
 HAL_Bool HAL_GetOutputsEnabled(void);
 
@@ -209,7 +218,12 @@
  */
 int32_t HAL_GetMatchInfo(HAL_MatchInfo* info);
 
-void HAL_RefreshDSData(void);
+/**
+ * Refresh the DS control word.
+ *
+ * @return true if updated
+ */
+HAL_Bool HAL_RefreshDSData(void);
 
 void HAL_ProvideNewDataEventHandle(WPI_EventHandle handle);
 void HAL_RemoveNewDataEventHandle(WPI_EventHandle handle);
diff --git a/hal/src/main/native/include/hal/DriverStationTypes.h b/hal/src/main/native/include/hal/DriverStationTypes.h
index 277c286..5917c51 100644
--- a/hal/src/main/native/include/hal/DriverStationTypes.h
+++ b/hal/src/main/native/include/hal/DriverStationTypes.h
@@ -42,6 +42,7 @@
 
 // clang-format off
 HAL_ENUM(HAL_AllianceStationID) {
+  HAL_AllianceStationID_kUnknown = 0,
   HAL_AllianceStationID_kRed1,
   HAL_AllianceStationID_kRed2,
   HAL_AllianceStationID_kRed3,
@@ -51,7 +52,7 @@
 };
 
 HAL_ENUM(HAL_MatchType) {
-  HAL_kMatchType_none,
+  HAL_kMatchType_none = 0,
   HAL_kMatchType_practice,
   HAL_kMatchType_qualification,
   HAL_kMatchType_elimination,
diff --git a/hal/src/main/native/include/hal/DutyCycle.h b/hal/src/main/native/include/hal/DutyCycle.h
index 90266fd..d5e655b 100644
--- a/hal/src/main/native/include/hal/DutyCycle.h
+++ b/hal/src/main/native/include/hal/DutyCycle.h
@@ -26,7 +26,7 @@
  * @param[in] triggerType the analog trigger type of the source if it is
  *                         an analog trigger
  * @param[out] status Error status variable. 0 on success.
- * @return thre created duty cycle handle
+ * @return the created duty cycle handle
  */
 HAL_DutyCycleHandle HAL_InitializeDutyCycle(HAL_Handle digitalSourceHandle,
                                             HAL_AnalogTriggerType triggerType,
diff --git a/hal/src/main/native/include/hal/Encoder.h b/hal/src/main/native/include/hal/Encoder.h
index a6bf4af..c6e16a6 100644
--- a/hal/src/main/native/include/hal/Encoder.h
+++ b/hal/src/main/native/include/hal/Encoder.h
@@ -83,7 +83,7 @@
 /**
  * Gets the current counts of the encoder after encoding type scaling.
  *
- * This is scaled by the value passed duing initialization to encodingType.
+ * This is scaled by the value passed during initialization to encodingType.
  *
  * @param[in] encoderHandle the encoder handle
  * @param[out] status Error status variable. 0 on success.
@@ -125,7 +125,7 @@
  */
 void HAL_ResetEncoder(HAL_EncoderHandle encoderHandle, int32_t* status);
 
-/*
+/**
  * Gets the Period of the most recent count.
  *
  * Returns the time interval of the most recent count. This can be used for
diff --git a/hal/src/main/native/include/hal/Extensions.h b/hal/src/main/native/include/hal/Extensions.h
index 6f64fdb..b39cc36 100644
--- a/hal/src/main/native/include/hal/Extensions.h
+++ b/hal/src/main/native/include/hal/Extensions.h
@@ -31,7 +31,7 @@
  * Expected to be called internally, not by users.
  *
  * @param library the library path
- * @return the succes state of the initialization
+ * @return the success state of the initialization
  */
 int HAL_LoadOneExtension(const char* library);
 
@@ -39,7 +39,7 @@
  * Loads any extra halsim libraries provided in the HALSIM_EXTENSIONS
  * environment variable.
  *
- * @return the succes state of the initialization
+ * @return the success state of the initialization
  */
 int HAL_LoadExtensions(void);
 
diff --git a/hal/src/main/native/include/hal/HALBase.h b/hal/src/main/native/include/hal/HALBase.h
index 1fe6b3a..fe8d1bf 100644
--- a/hal/src/main/native/include/hal/HALBase.h
+++ b/hal/src/main/native/include/hal/HALBase.h
@@ -18,7 +18,7 @@
 
 /**
  * @defgroup hal_capi WPILib HAL API
- * Hardware Abstraction Layer to hardware or simulator
+ * Hardware Abstraction Layer (HAL) to hardware or simulator
  * @{
  */
 
@@ -75,9 +75,9 @@
 int64_t HAL_GetFPGARevision(int32_t* status);
 
 /**
- * Returns the serial number.
+ * Returns the roboRIO serial number.
  *
- * @param[out] buffer The serial number.
+ * @param[out] buffer The roboRIO serial number.
  * @param size The maximum characters to copy into buffer.
  * @return Number of characters copied into buffer.
  */
@@ -93,6 +93,12 @@
 size_t HAL_GetComments(char* buffer, size_t size);
 
 /**
+ * Returns the team number configured for the robot controller.
+ * @return team number, or 0 if not found.
+ */
+int32_t HAL_GetTeamNumber(void);
+
+/**
  * Returns the runtime type of the HAL.
  *
  * @return HAL Runtime Type
@@ -108,7 +114,7 @@
 HAL_Bool HAL_GetFPGAButton(int32_t* status);
 
 /**
- * Gets if the system outputs are currently active
+ * Gets if the system outputs are currently active.
  *
  * @param[out] status the error code, or 0 for success
  * @return true if the system outputs are active, false if disabled
@@ -173,6 +179,22 @@
 uint64_t HAL_ExpandFPGATime(uint32_t unexpandedLower, int32_t* status);
 
 /**
+ * Gets the current state of the Robot Signal Light (RSL).
+ *
+ * @param[out] status the error code, or 0 for success
+ * @return The current state of the RSL- true if on, false if off
+ */
+HAL_Bool HAL_GetRSLState(int32_t* status);
+
+/**
+ * Gets if the system time is valid.
+ *
+ * @param[out] status the error code, or 0 for success
+ * @return True if the system time is valid, false otherwise
+ */
+HAL_Bool HAL_GetSystemTimeValid(int32_t* status);
+
+/**
  * Call this to start up HAL. This is required for robot programs.
  *
  * This must be called before any other HAL functions. Failure to do so will
diff --git a/hal/src/main/native/include/hal/Main.h b/hal/src/main/native/include/hal/Main.h
index 712ad01..9133135 100644
--- a/hal/src/main/native/include/hal/Main.h
+++ b/hal/src/main/native/include/hal/Main.h
@@ -7,7 +7,7 @@
 #include "hal/Types.h"
 
 /**
- * @defgroup hal_relay Main loop functions
+ * @defgroup hal_main Main loop functions
  * @ingroup hal_capi
  * @{
  */
diff --git a/hal/src/main/native/include/hal/Notifier.h b/hal/src/main/native/include/hal/Notifier.h
index 96452f4..9b451e4 100644
--- a/hal/src/main/native/include/hal/Notifier.h
+++ b/hal/src/main/native/include/hal/Notifier.h
@@ -63,7 +63,8 @@
 /**
  * Stops a notifier from running.
  *
- * This will cause any call into HAL_WaitForNotifierAlarm to return.
+ * This will cause any call into HAL_WaitForNotifierAlarm to return with time =
+ * 0.
  *
  * @param[in] notifierHandle the notifier handle
  * @param[out] status Error status variable. 0 on success.
diff --git a/hal/src/main/native/include/hal/PWM.h b/hal/src/main/native/include/hal/PWM.h
index df9020b..d308f8e 100644
--- a/hal/src/main/native/include/hal/PWM.h
+++ b/hal/src/main/native/include/hal/PWM.h
@@ -50,7 +50,7 @@
 /**
  * Sets the configuration settings for the PWM channel.
  *
- * All values are in milliseconds.
+ * All values are in microseconds.
  *
  * @param[in] pwmPortHandle  the PWM handle
  * @param[in] maxPwm         the maximum PWM value
@@ -60,17 +60,15 @@
  * @param[in] minPwm         the minimum PWM value
  * @param[out] status        Error status variable. 0 on success.
  */
-void HAL_SetPWMConfig(HAL_DigitalHandle pwmPortHandle, double maxPwm,
-                      double deadbandMaxPwm, double centerPwm,
-                      double deadbandMinPwm, double minPwm, int32_t* status);
+void HAL_SetPWMConfigMicroseconds(HAL_DigitalHandle pwmPortHandle,
+                                  int32_t maxPwm, int32_t deadbandMaxPwm,
+                                  int32_t centerPwm, int32_t deadbandMinPwm,
+                                  int32_t minPwm, int32_t* status);
 
 /**
- * Sets the raw configuration settings for the PWM channel.
+ * Gets the pwm configuration settings for the PWM channel.
  *
- * We recommend using HAL_SetPWMConfig() instead, as those values are properly
- * scaled. Usually used for values grabbed by HAL_GetPWMConfigRaw().
- *
- * Values are in raw FPGA units.
+ * Values are in microseconds.
  *
  * @param[in] pwmPortHandle  the PWM handle
  * @param[in] maxPwm         the maximum PWM value
@@ -80,29 +78,10 @@
  * @param[in] minPwm         the minimum PWM value
  * @param[out] status        Error status variable. 0 on success.
  */
-void HAL_SetPWMConfigRaw(HAL_DigitalHandle pwmPortHandle, int32_t maxPwm,
-                         int32_t deadbandMaxPwm, int32_t centerPwm,
-                         int32_t deadbandMinPwm, int32_t minPwm,
-                         int32_t* status);
-
-/**
- * Gets the raw pwm configuration settings for the PWM channel.
- *
- * Values are in raw FPGA units. These units have the potential to change for
- * any FPGA release.
- *
- * @param[in] pwmPortHandle  the PWM handle
- * @param[in] maxPwm         the maximum PWM value
- * @param[in] deadbandMaxPwm the high range of the center deadband
- * @param[in] centerPwm      the center PWM value
- * @param[in] deadbandMinPwm the low range of the center deadband
- * @param[in] minPwm         the minimum PWM value
- * @param[out] status        Error status variable. 0 on success.
- */
-void HAL_GetPWMConfigRaw(HAL_DigitalHandle pwmPortHandle, int32_t* maxPwm,
-                         int32_t* deadbandMaxPwm, int32_t* centerPwm,
-                         int32_t* deadbandMinPwm, int32_t* minPwm,
-                         int32_t* status);
+void HAL_GetPWMConfigMicroseconds(HAL_DigitalHandle pwmPortHandle,
+                                  int32_t* maxPwm, int32_t* deadbandMaxPwm,
+                                  int32_t* centerPwm, int32_t* deadbandMinPwm,
+                                  int32_t* minPwm, int32_t* status);
 
 /**
  * Sets if the FPGA should output the center value if the input value is within
@@ -126,17 +105,16 @@
                                      int32_t* status);
 
 /**
- * Sets a PWM channel to the desired value.
+ * Sets a PWM channel to the desired pulse width in microseconds.
  *
- * The values are in raw FPGA units, and have the potential to change with any
- * FPGA release.
  *
  * @param[in] pwmPortHandle the PWM handle
- * @param[in] value         the PWM value to set
+ * @param[in] microsecondPulseTime  the PWM value to set
  * @param[out] status       Error status variable. 0 on success.
  */
-void HAL_SetPWMRaw(HAL_DigitalHandle pwmPortHandle, int32_t value,
-                   int32_t* status);
+void HAL_SetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
+                                     int32_t microsecondPulseTime,
+                                     int32_t* status);
 
 /**
  * Sets a PWM channel to the desired scaled value.
@@ -177,16 +155,14 @@
 void HAL_SetPWMDisabled(HAL_DigitalHandle pwmPortHandle, int32_t* status);
 
 /**
- * Gets a value from a PWM channel.
- *
- * The values are in raw FPGA units, and have the potential to change with any
- * FPGA release.
+ * Gets the current microsecond pulse time from a PWM channel.
  *
  * @param[in] pwmPortHandle the PWM handle
  * @param[out] status       Error status variable. 0 on success.
- * @return the current raw PWM value
+ * @return the current PWM microsecond pulse time
  */
-int32_t HAL_GetPWMRaw(HAL_DigitalHandle pwmPortHandle, int32_t* status);
+int32_t HAL_GetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
+                                        int32_t* status);
 
 /**
  * Gets a scaled value from a PWM channel.
@@ -229,6 +205,14 @@
                            int32_t* status);
 
 /**
+ * Sets the PWM output to be a continuous high signal while enabled.
+ *
+ * @param[in] pwmPortHandle the PWM handle.
+ * @param[out] status       Error status variable. 0 on success.
+ */
+void HAL_SetPWMAlwaysHighMode(HAL_DigitalHandle pwmPortHandle, int32_t* status);
+
+/**
  * Gets the loop timing of the PWM system.
  *
  * @param[out] status Error status variable. 0 on success.
diff --git a/hal/src/main/native/include/hal/Ports.h b/hal/src/main/native/include/hal/Ports.h
index a212446..a6c610a 100644
--- a/hal/src/main/native/include/hal/Ports.h
+++ b/hal/src/main/native/include/hal/Ports.h
@@ -45,7 +45,7 @@
 int32_t HAL_GetNumAnalogOutputs(void);
 
 /**
- * Gets the number of analog counters in the current system.
+ * Gets the number of counters in the current system.
  *
  * @return the number of counters
  */
diff --git a/hal/src/main/native/include/hal/Power.h b/hal/src/main/native/include/hal/Power.h
index 2bd983a..b2a0169 100644
--- a/hal/src/main/native/include/hal/Power.h
+++ b/hal/src/main/native/include/hal/Power.h
@@ -67,6 +67,14 @@
 int32_t HAL_GetUserCurrentFaults6V(int32_t* status);
 
 /**
+ * Enables or disables the 6V rail.
+ *
+ * @param enabled whether the rail should be enabled
+ * @param[out] status the error code, or 0 for success
+ */
+void HAL_SetUserRailEnabled6V(HAL_Bool enabled, int32_t* status);
+
+/**
  * Gets the 5V rail voltage.
  *
  * @param[out] status the error code, or 0 for success
@@ -99,6 +107,14 @@
 int32_t HAL_GetUserCurrentFaults5V(int32_t* status);
 
 /**
+ * Enables or disables the 5V rail.
+ *
+ * @param enabled whether the rail should be enabled
+ * @param[out] status the error code, or 0 for success
+ */
+void HAL_SetUserRailEnabled5V(HAL_Bool enabled, int32_t* status);
+
+/**
  * Gets the 3V3 rail voltage.
  *
  * @param[out] status the error code, or 0 for success
@@ -131,6 +147,14 @@
 int32_t HAL_GetUserCurrentFaults3V3(int32_t* status);
 
 /**
+ * Enables or disables the 3V3 rail.
+ *
+ * @param enabled whether the rail should be enabled
+ * @param[out] status the error code, or 0 for success
+ */
+void HAL_SetUserRailEnabled3V3(HAL_Bool enabled, int32_t* status);
+
+/**
  * Get the current brownout voltage setting.
  *
  * @param[out] status the error code, or 0 for success
@@ -149,6 +173,14 @@
  */
 void HAL_SetBrownoutVoltage(double voltage, int32_t* status);
 
+/**
+ * Get the current CPU temperature in degrees Celsius
+ *
+ * @param[out] status the error code, or 0 for success
+ * @return current CPU temperature in degrees Celsius
+ */
+double HAL_GetCPUTemp(int32_t* status);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/hal/src/main/native/include/hal/PowerDistribution.h b/hal/src/main/native/include/hal/PowerDistribution.h
index 7c2b582..47543bb 100644
--- a/hal/src/main/native/include/hal/PowerDistribution.h
+++ b/hal/src/main/native/include/hal/PowerDistribution.h
@@ -17,7 +17,7 @@
 
 // clang-format off
 /**
- * The acceptable accelerometer ranges.
+ * The types of power distribution devices.
  */
 HAL_ENUM(HAL_PowerDistributionType) {
   HAL_PowerDistributionType_kAutomatic = 0,
@@ -36,10 +36,10 @@
  * Initializes a Power Distribution Panel.
  *
  * @param[in] moduleNumber       the module number to initialize
- * @param[in] type               the type of module to intialize
+ * @param[in] type               the type of module to initialize
  * @param[in] allocationLocation the location where the allocation is occurring
  * @param[out] status            Error status variable. 0 on success.
- * @return the created PowerDistribution
+ * @return the created PowerDistribution handle
  */
 HAL_PowerDistributionHandle HAL_InitializePowerDistribution(
     int32_t moduleNumber, HAL_PowerDistributionType type,
@@ -134,7 +134,7 @@
     HAL_PowerDistributionHandle handle, int32_t channel, int32_t* status);
 
 /**
- * Gets the current of all 24 channels on the PowerDistribution.
+ * Gets the current of all channels on the PowerDistribution.
  *
  * The array must be large enough to hold all channels.
  *
@@ -214,6 +214,7 @@
  *
  * @param[in] handle the module handle
  * @param[out] status Error status variable. 0 on success.
+ * @return the state of the switchable channel
  */
 HAL_Bool HAL_GetPowerDistributionSwitchableChannel(
     HAL_PowerDistributionHandle handle, int32_t* status);
@@ -291,12 +292,34 @@
   uint32_t hasReset : 1;
 };
 
+/**
+ * Get the version of the PowerDistribution.
+ *
+ * @param[in] handle the module handle
+ * @param[out] version the HAL_PowerDistributionVersion to populate
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_GetPowerDistributionVersion(HAL_PowerDistributionHandle handle,
                                      HAL_PowerDistributionVersion* version,
                                      int32_t* status);
+/**
+ * Get the current faults of the PowerDistribution.
+ *
+ * @param[in] handle the module handle
+ * @param[out] faults the HAL_PowerDistributionFaults to populate
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_GetPowerDistributionFaults(HAL_PowerDistributionHandle handle,
                                     HAL_PowerDistributionFaults* faults,
                                     int32_t* status);
+
+/**
+ * Gets the sticky faults of the PowerDistribution.
+ *
+ * @param[in] handle the module handle
+ * @param[out] stickyFaults the HAL_PowerDistributionStickyFaults to populate
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_GetPowerDistributionStickyFaults(
     HAL_PowerDistributionHandle handle,
     HAL_PowerDistributionStickyFaults* stickyFaults, int32_t* status);
diff --git a/hal/src/main/native/include/hal/REVPH.h b/hal/src/main/native/include/hal/REVPH.h
index 430c53d..4476675 100644
--- a/hal/src/main/native/include/hal/REVPH.h
+++ b/hal/src/main/native/include/hal/REVPH.h
@@ -9,7 +9,7 @@
 #include "hal/Types.h"
 
 /**
- * @defgroup hal_rev_ph REV PH Functions
+ * @defgroup hal_rev_ph REV Pneumatic Hub (PH) Functions
  * @ingroup hal_capi
  * @{
  */
@@ -91,58 +91,279 @@
 extern "C" {
 #endif
 
+/**
+ * Initializes a PH.
+ *
+ * @param[in] module             the CAN ID to initialize
+ * @param[in] allocationLocation the location where the allocation is occurring
+ *                               (can be null)
+ * @param[out] status            Error status variable. 0 on success.
+ * @return the created PH handle
+ */
 HAL_REVPHHandle HAL_InitializeREVPH(int32_t module,
                                     const char* allocationLocation,
                                     int32_t* status);
 
+/**
+ * Frees a PH handle.
+ *
+ * @param[in] handle the PH handle
+ */
 void HAL_FreeREVPH(HAL_REVPHHandle handle);
 
+/**
+ * Checks if a solenoid channel number is valid.
+ *
+ * @param[in] channel the channel to check
+ * @return true if the channel is valid, otherwise false
+ */
 HAL_Bool HAL_CheckREVPHSolenoidChannel(int32_t channel);
+
+/**
+ * Checks if a PH module (CAN ID) is valid.
+ *
+ * @param[in] module the module to check
+ * @return true if the module is valid, otherwise false
+ */
 HAL_Bool HAL_CheckREVPHModuleNumber(int32_t module);
 
+/**
+ * Get whether compressor is turned on.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return true if the compressor is turned on
+ */
 HAL_Bool HAL_GetREVPHCompressor(HAL_REVPHHandle handle, int32_t* status);
+
+/**
+ * Send compressor configuration to the PH.
+ *
+ * @param[in] handle  the PH handle
+ * @param[in] config  compressor configuration
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_SetREVPHCompressorConfig(HAL_REVPHHandle handle,
                                   const HAL_REVPHCompressorConfig* config,
                                   int32_t* status);
+
+/**
+ * Disable Compressor.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_SetREVPHClosedLoopControlDisabled(HAL_REVPHHandle handle,
                                            int32_t* status);
+
+/**
+ * Enables the compressor in digital mode using the digital pressure switch. The
+ * compressor will turn on when the pressure switch indicates that the system is
+ * not full, and will turn off when the pressure switch indicates that the
+ * system is full.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_SetREVPHClosedLoopControlDigital(HAL_REVPHHandle handle,
                                           int32_t* status);
+
+/**
+ * Enables the compressor in analog mode. This mode uses an analog
+ * pressure sensor connected to analog channel 0 to cycle the compressor. The
+ * compressor will turn on when the pressure drops below minAnalogVoltage and
+ * will turn off when the pressure reaches maxAnalogVoltage. This mode is only
+ * supported by the REV PH with the REV Analog Pressure Sensor connected to
+ * analog channel 0.
+ * @param[in] handle  the PH handle
+ * @param[in] minAnalogVoltage The compressor will turn on when the analog
+ * pressure sensor voltage drops below this value
+ * @param[in] maxAnalogVoltage The compressor will turn off when the analog
+ * pressure sensor reaches this value.
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_SetREVPHClosedLoopControlAnalog(HAL_REVPHHandle handle,
                                          double minAnalogVoltage,
                                          double maxAnalogVoltage,
                                          int32_t* status);
+
+/**
+ * Enables the compressor in hybrid mode. This mode uses both a digital
+ * pressure switch and an analog pressure sensor connected to analog channel 0
+ * to cycle the compressor.
+ *
+ * The compressor will turn on when \a both:
+ *
+ * - The digital pressure switch indicates the system is not full AND
+ * - The analog pressure sensor indicates that the pressure in the system is
+ * below the specified minimum pressure.
+ *
+ * The compressor will turn off when \a either:
+ *
+ * - The digital pressure switch is disconnected or indicates that the system
+ * is full OR
+ * - The pressure detected by the analog sensor is greater than the specified
+ * maximum pressure.
+ *
+ * @param[in] handle  the PH handle
+ * @param[in] minAnalogVoltage The compressor will turn on when the analog
+ * pressure sensor voltage drops below this value and the pressure switch
+ * indicates that the system is not full.
+ * @param[in] maxAnalogVoltage The compressor will turn off when the analog
+ * pressure sensor reaches this value or the pressure switch is disconnected or
+ * indicates that the system is full.
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_SetREVPHClosedLoopControlHybrid(HAL_REVPHHandle handle,
                                          double minAnalogVoltage,
                                          double maxAnalogVoltage,
                                          int32_t* status);
+
+/**
+ * Get compressor configuration from the PH.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return compressor configuration
+ */
 HAL_REVPHCompressorConfigType HAL_GetREVPHCompressorConfig(
     HAL_REVPHHandle handle, int32_t* status);
+
+/**
+ * Returns the state of the digital pressure switch.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return True if pressure switch indicates that the system is full,
+ * otherwise false.
+ */
 HAL_Bool HAL_GetREVPHPressureSwitch(HAL_REVPHHandle handle, int32_t* status);
+
+/**
+ * Returns the current drawn by the compressor.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return The current drawn by the compressor in amps.
+ */
 double HAL_GetREVPHCompressorCurrent(HAL_REVPHHandle handle, int32_t* status);
+
+/**
+ * Returns the raw voltage of the specified analog
+ * input channel.
+ *
+ * @param[in] handle  the PH handle
+ * @param[in] channel The analog input channel to read voltage from.
+ * @param[out] status Error status variable. 0 on success.
+ * @return The voltage of the specified analog input channel in volts.
+ */
 double HAL_GetREVPHAnalogVoltage(HAL_REVPHHandle handle, int32_t channel,
                                  int32_t* status);
+
+/**
+ * Returns the current input voltage for the PH.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return The input voltage in volts.
+ */
 double HAL_GetREVPHVoltage(HAL_REVPHHandle handle, int32_t* status);
+
+/**
+ * Returns the current voltage of the regulated 5v supply.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return The current voltage of the 5v supply in volts.
+ */
 double HAL_GetREVPH5VVoltage(HAL_REVPHHandle handle, int32_t* status);
+
+/**
+ * Returns the total current drawn by all solenoids.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return Total current drawn by all solenoids in amps.
+ */
 double HAL_GetREVPHSolenoidCurrent(HAL_REVPHHandle handle, int32_t* status);
+
+/**
+ * Returns the current voltage of the solenoid power supply.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return The current voltage of the solenoid power supply in volts.
+ */
 double HAL_GetREVPHSolenoidVoltage(HAL_REVPHHandle handle, int32_t* status);
+
+/**
+ * Returns the hardware and firmware versions of the PH.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] version The hardware and firmware versions.
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_GetREVPHVersion(HAL_REVPHHandle handle, HAL_REVPHVersion* version,
                          int32_t* status);
 
+/**
+ * Gets a bitmask of solenoid values.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] status Error status variable. 0 on success.
+ * @return solenoid values
+ */
 int32_t HAL_GetREVPHSolenoids(HAL_REVPHHandle handle, int32_t* status);
+
+/**
+ * Sets solenoids on a PH.
+ *
+ * @param[in] handle  the PH handle
+ * @param[in] mask bitmask to set
+ * @param[in] values solenoid values
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_SetREVPHSolenoids(HAL_REVPHHandle handle, int32_t mask, int32_t values,
                            int32_t* status);
 
+/**
+ * Fire a single solenoid shot for the specified duration.
+ *
+ * @param[in] handle  the PH handle
+ * @param[in] index solenoid index
+ * @param[in] durMs shot duration in ms
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_FireREVPHOneShot(HAL_REVPHHandle handle, int32_t index, int32_t durMs,
                           int32_t* status);
 
+/**
+ * Returns the faults currently active on the PH.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] faults The faults.
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_GetREVPHFaults(HAL_REVPHHandle handle, HAL_REVPHFaults* faults,
                         int32_t* status);
 
+/**
+ * Returns the sticky faults currently active on this device.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] stickyFaults The sticky faults.
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_GetREVPHStickyFaults(HAL_REVPHHandle handle,
                               HAL_REVPHStickyFaults* stickyFaults,
                               int32_t* status);
 
+/**
+ * Clears the sticky faults.
+ *
+ * @param[in] handle  the PH handle
+ * @param[out] status Error status variable. 0 on success.
+ */
 void HAL_ClearREVPHStickyFaults(HAL_REVPHHandle handle, int32_t* status);
 
 #ifdef __cplusplus
diff --git a/hal/src/main/native/include/hal/SPI.h b/hal/src/main/native/include/hal/SPI.h
index f3c7fdc..32644b6 100644
--- a/hal/src/main/native/include/hal/SPI.h
+++ b/hal/src/main/native/include/hal/SPI.h
@@ -108,7 +108,7 @@
  *
  * @param port  The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for
  * MXP
- * @returns     The SPI mode currently set
+ * @return      The SPI mode currently set
  */
 HAL_SPIMode HAL_GetSPIMode(HAL_SPIPort port);
 
@@ -172,7 +172,7 @@
  *
  * @param[in] port    The number of the port to use. 0-3 for Onboard CS0-CS2, 4
  *                    for MXP.
- * @param[in] period  The accumlation period (seconds).
+ * @param[in] period  The accumulation period (seconds).
  * @param[out] status the error code, or 0 for success
  */
 void HAL_StartSPIAutoRate(HAL_SPIPort port, double period, int32_t* status);
@@ -199,7 +199,7 @@
                              int32_t* status);
 
 /**
- * Stops an automatic SPI accumlation.
+ * Stops an automatic SPI accumulation.
  *
  * @param[in] port    The number of the port to use. 0-3 for Onboard CS0-CS2, 4
  *                    for MXP.
diff --git a/hal/src/main/native/include/hal/SerialPort.h b/hal/src/main/native/include/hal/SerialPort.h
index cd6140e..f4a357e 100644
--- a/hal/src/main/native/include/hal/SerialPort.h
+++ b/hal/src/main/native/include/hal/SerialPort.h
@@ -30,11 +30,12 @@
 /**
  * Initializes a serial port.
  *
- * The channels are either the onboard RS232, the mxp uart, or 2 USB ports. The
+ * The channels are either the onboard RS232, the MXP UART, or 2 USB ports. The
  * top port is USB1, the bottom port is USB2.
  *
  * @param[in] port the serial port to initialize
  * @param[out] status the error code, or 0 for success
+ * @return Serial Port Handle
  */
 HAL_SerialPortHandle HAL_InitializeSerialPort(HAL_SerialPort port,
                                               int32_t* status);
@@ -48,6 +49,7 @@
  * @param[in] port     the serial port to initialize
  * @param[in] portName the dev port name
  * @param[out] status  the error code, or 0 for success
+ * @return Serial Port Handle
  */
 HAL_SerialPortHandle HAL_InitializeSerialPortDirect(HAL_SerialPort port,
                                                     const char* portName,
diff --git a/hal/src/main/native/include/hal/SimDevice.h b/hal/src/main/native/include/hal/SimDevice.h
index f90cb9b..0e75cea 100644
--- a/hal/src/main/native/include/hal/SimDevice.h
+++ b/hal/src/main/native/include/hal/SimDevice.h
@@ -9,6 +9,7 @@
 #ifdef __cplusplus
 #include <initializer_list>
 #include <span>
+#include <string>
 #endif
 
 #include "hal/Types.h"
@@ -46,7 +47,7 @@
  *
  * The device name must be unique.  0 is returned if the device name already
  * exists.  If multiple instances of the same device are desired, recommend
- * appending the instance/unique identifer in brackets to the base name,
+ * appending the instance/unique identifier in brackets to the base name,
  * e.g. "device[1]".
  *
  * 0 is returned if not in simulation.
@@ -67,6 +68,14 @@
 void HAL_FreeSimDevice(HAL_SimDeviceHandle handle);
 
 /**
+ * Get the name of a simulated device
+ *
+ * @param handle simulated device handle
+ * @return name of the simulated device
+ */
+const char* HAL_GetSimDeviceName(HAL_SimDeviceHandle handle);
+
+/**
  * Creates a value on a simulated device.
  *
  * Returns 0 if not in simulation; this can be used to avoid calls
@@ -400,7 +409,7 @@
   /**
    * Wraps a simulated value handle as returned by HAL_CreateSimValue().
    *
-   * @param handle simulated value handle
+   * @param val simulated value handle
    */
   /*implicit*/ SimValue(HAL_SimValueHandle val)  // NOLINT
       : m_handle(val) {}
@@ -452,7 +461,7 @@
   /**
    * Wraps a simulated value handle as returned by HAL_CreateSimValueInt().
    *
-   * @param handle simulated value handle
+   * @param val simulated value handle
    */
   /*implicit*/ SimInt(HAL_SimValueHandle val)  // NOLINT
       : SimValue(val) {}
@@ -493,7 +502,7 @@
   /**
    * Wraps a simulated value handle as returned by HAL_CreateSimValueLong().
    *
-   * @param handle simulated value handle
+   * @param val simulated value handle
    */
   /*implicit*/ SimLong(HAL_SimValueHandle val)  // NOLINT
       : SimValue(val) {}
@@ -534,7 +543,7 @@
   /**
    * Wraps a simulated value handle as returned by HAL_CreateSimValueDouble().
    *
-   * @param handle simulated value handle
+   * @param val simulated value handle
    */
   /*implicit*/ SimDouble(HAL_SimValueHandle val)  // NOLINT
       : SimValue(val) {}
@@ -575,7 +584,7 @@
   /**
    * Wraps a simulated value handle as returned by HAL_CreateSimValueEnum().
    *
-   * @param handle simulated value handle
+   * @param val simulated value handle
    */
   /*implicit*/ SimEnum(HAL_SimValueHandle val)  // NOLINT
       : SimValue(val) {}
@@ -609,7 +618,7 @@
   /**
    * Wraps a simulated value handle as returned by HAL_CreateSimValueBoolean().
    *
-   * @param handle simulated value handle
+   * @param val simulated value handle
    */
   /*implicit*/ SimBoolean(HAL_SimValueHandle val)  // NOLINT
       : SimValue(val) {}
@@ -654,7 +663,7 @@
    *
    * The device name must be unique.  Returns null if the device name
    * already exists.  If multiple instances of the same device are desired,
-   * recommend appending the instance/unique identifer in brackets to the base
+   * recommend appending the instance/unique identifier in brackets to the base
    * name, e.g. "device[1]".
    *
    * If not in simulation, results in an "empty" object that evaluates to false
@@ -732,6 +741,15 @@
   operator HAL_SimDeviceHandle() const { return m_handle; }  // NOLINT
 
   /**
+   * Get the name of the simulated device.
+   *
+   * @return name
+   */
+  std::string GetName() const {
+    return std::string(HAL_GetSimDeviceName(m_handle));
+  }
+
+  /**
    * Creates a value on the simulated device.
    *
    * If not in simulation, results in an "empty" object that evaluates to false
diff --git a/hal/src/main/native/include/hal/cpp/UnsafeDIO.h b/hal/src/main/native/include/hal/cpp/UnsafeDIO.h
index c849fd0..e7f286b 100644
--- a/hal/src/main/native/include/hal/cpp/UnsafeDIO.h
+++ b/hal/src/main/native/include/hal/cpp/UnsafeDIO.h
@@ -63,8 +63,8 @@
 
 /**
  * Unsafe digital output set function
- * This function can be used to perform fast and determinstically set digital
- * outputs. This function holds the DIO lock, so calling anyting other then
+ * This function can be used to perform fast and deterministically set digital
+ * outputs. This function holds the DIO lock, so calling anything other then
  * functions on the Proxy object passed as a parameter can deadlock your
  * program.
  *
diff --git a/hal/src/main/native/include/hal/handles/UnlimitedHandleResource.h b/hal/src/main/native/include/hal/handles/UnlimitedHandleResource.h
index 09510ac..2048f62 100644
--- a/hal/src/main/native/include/hal/handles/UnlimitedHandleResource.h
+++ b/hal/src/main/native/include/hal/handles/UnlimitedHandleResource.h
@@ -19,7 +19,7 @@
 
 /**
  * The UnlimitedHandleResource class is a way to track handles. This version
- * allows an unlimted number of handles that are allocated sequentially. When
+ * allows an unlimited number of handles that are allocated sequentially. When
  * possible, indices are reused to save memory usage and keep the array length
  * down.
  * However, automatic array management has not been implemented, but might be in
diff --git a/hal/src/main/native/include/hal/roborio/HMB.h b/hal/src/main/native/include/hal/roborio/HMB.h
new file mode 100644
index 0000000..fc7381b
--- /dev/null
+++ b/hal/src/main/native/include/hal/roborio/HMB.h
@@ -0,0 +1,112 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <stdint.h>
+
+struct HAL_HMBData {
+  struct AnalogInputs {
+    uint32_t Values[8];
+    uint32_t Reserved[8];
+  } AnalogInputs;
+  struct AveragedAnalogInputs {
+    uint32_t Values[8];
+    uint32_t Reserved[8];
+  } AveragedAnalogInputs;
+  struct Accumulator0 {
+    uint32_t Count;
+    uint32_t Value0;
+    uint32_t Value1;
+    uint32_t Reserved[13];
+  } Accumulator0;
+  struct Accumulator1 {
+    uint32_t Count;
+    uint32_t Value0;
+    uint32_t Value1;
+    uint32_t Reserved[13];
+  } Accumulator1;
+  struct DI {
+    uint32_t Values;
+    uint32_t FilteredValues;
+    uint32_t Reserved[14];
+  } DI;
+  struct AnalogTriggers {
+    struct Trigger {
+      uint8_t InHysteresis0 : 1;
+      uint8_t OverLimit0 : 1;
+      uint8_t Rising0 : 1;
+      uint8_t Falling0 : 1;
+      uint8_t InHysteresis1 : 1;
+      uint8_t OverLimit1 : 1;
+      uint8_t Rising1 : 1;
+      uint8_t Falling1 : 1;
+    } Trigger[4];
+    uint32_t Reserved[15];
+  } AnalogTriggers;
+  struct Counters {
+    struct Counter {
+      uint32_t Direction : 1;
+      int32_t Value : 31;
+    } Counter[8];
+    uint32_t Reserved[8];
+  } Counters;
+  struct CounterTimers {
+    struct Timer {
+      uint32_t Period : 23;
+      int32_t Count : 8;
+      uint32_t Stalled : 1;
+    } Timer[8];
+    uint32_t Reserved[8];
+  } CounterTimers;
+  struct Encoders {
+    struct Encoder {
+      uint32_t Direction : 1;
+      int32_t Value : 31;
+    } Encoder[8];
+    uint32_t Reserved[8];
+  } Encoders;
+  struct EncoderTimers {
+    struct Timer {
+      uint32_t Period : 23;
+      int32_t Count : 8;
+      uint32_t Stalled : 1;
+    } Timer[8];
+    uint32_t Reserved[8];
+  } EncoderTimers;
+  struct DutyCycle {
+    uint32_t Output[8];
+    uint32_t Reserved[8];
+  } DutyCycle;
+  struct Interrupts {
+    struct Interrupt {
+      uint32_t FallingTimestamp;
+      uint32_t RisingTimestamp;
+    } Interrupt[8];
+  } Interrupts;
+  struct PWM {
+    uint32_t Headers[10];
+    uint32_t Reserved[6];
+    uint32_t MXP[10];
+    uint32_t Reserved2[6];
+  } PWM;
+  struct RelayDOAO {
+    uint32_t Relays;
+    uint32_t Reserved;
+    uint32_t AO[2];
+    uint32_t Reserved2[12];
+  } RelayDOAO;
+  struct Timestamp {
+    uint32_t Lower;
+    uint32_t Upper;
+    uint32_t Reserved[14];
+  } Timestamp;
+};
+
+extern "C" {
+
+void HAL_InitializeHMB(int32_t* status);
+
+const volatile HAL_HMBData* HAL_GetHMBBuffer(void);
+}  // extern "C"
diff --git a/hal/src/main/native/include/hal/simulation/PWMData.h b/hal/src/main/native/include/hal/simulation/PWMData.h
index 91d22df..8357fa2 100644
--- a/hal/src/main/native/include/hal/simulation/PWMData.h
+++ b/hal/src/main/native/include/hal/simulation/PWMData.h
@@ -20,12 +20,13 @@
 HAL_Bool HALSIM_GetPWMInitialized(int32_t index);
 void HALSIM_SetPWMInitialized(int32_t index, HAL_Bool initialized);
 
-int32_t HALSIM_RegisterPWMRawValueCallback(int32_t index,
-                                           HAL_NotifyCallback callback,
-                                           void* param, HAL_Bool initialNotify);
-void HALSIM_CancelPWMRawValueCallback(int32_t index, int32_t uid);
-int32_t HALSIM_GetPWMRawValue(int32_t index);
-void HALSIM_SetPWMRawValue(int32_t index, int32_t rawValue);
+int32_t HALSIM_RegisterPWMPulseMicrosecondCallback(int32_t index,
+                                                   HAL_NotifyCallback callback,
+                                                   void* param,
+                                                   HAL_Bool initialNotify);
+void HALSIM_CancelPWMPulseMicrosecondCallback(int32_t index, int32_t uid);
+int32_t HALSIM_GetPWMPulseMicrosecond(int32_t index);
+void HALSIM_SetPWMPulseMicrosecond(int32_t index, int32_t microsecondPulseTime);
 
 int32_t HALSIM_RegisterPWMSpeedCallback(int32_t index,
                                         HAL_NotifyCallback callback,
diff --git a/hal/src/main/native/include/hal/simulation/RoboRioData.h b/hal/src/main/native/include/hal/simulation/RoboRioData.h
index 864be5c..d191fcb 100644
--- a/hal/src/main/native/include/hal/simulation/RoboRioData.h
+++ b/hal/src/main/native/include/hal/simulation/RoboRioData.h
@@ -126,6 +126,13 @@
 double HALSIM_GetRoboRioBrownoutVoltage(void);
 void HALSIM_SetRoboRioBrownoutVoltage(double brownoutVoltage);
 
+int32_t HALSIM_RegisterRoboRioTeamNumberCallback(HAL_NotifyCallback callback,
+                                                 void* param,
+                                                 HAL_Bool initialNotify);
+void HALSIM_CancelRoboRioTeamNumberCallback(int32_t uid);
+int32_t HALSIM_GetRoboRioTeamNumber(void);
+void HALSIM_SetRoboRioTeamNumber(int32_t teamNumber);
+
 int32_t HALSIM_RegisterRoboRioSerialNumberCallback(
     HAL_RoboRioStringCallback callback, void* param, HAL_Bool initialNotify);
 void HALSIM_CancelRoboRioSerialNumberCallback(int32_t uid);
@@ -141,6 +148,13 @@
 void HALSIM_RegisterRoboRioAllCallbacks(HAL_NotifyCallback callback,
                                         void* param, HAL_Bool initialNotify);
 
+int32_t HALSIM_RegisterRoboRioCPUTempCallback(HAL_NotifyCallback callback,
+                                              void* param,
+                                              HAL_Bool initialNotify);
+void HALSIM_CancelRoboRioCPUTempCallback(int32_t uid);
+double HALSIM_GetRoboRioCPUTemp(void);
+void HALSIM_SetRoboRioCPUTemp(double cpuTemp);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/hal/src/main/native/sim/AddressableLED.cpp b/hal/src/main/native/sim/AddressableLED.cpp
index 75a09fb..bce3f1d 100644
--- a/hal/src/main/native/sim/AddressableLED.cpp
+++ b/hal/src/main/native/sim/AddressableLED.cpp
@@ -139,17 +139,17 @@
         status,
         fmt::format(
             "Data length must be less than or equal to {}. {} was requested",
-            SimAddressableLEDData[led->index].length, length));
+            SimAddressableLEDData[led->index].length.Get(), length));
     return;
   }
   SimAddressableLEDData[led->index].SetData(data, length);
 }
 
 void HAL_SetAddressableLEDBitTiming(HAL_AddressableLEDHandle handle,
-                                    int32_t lowTime0NanoSeconds,
                                     int32_t highTime0NanoSeconds,
-                                    int32_t lowTime1NanoSeconds,
+                                    int32_t lowTime0NanoSeconds,
                                     int32_t highTime1NanoSeconds,
+                                    int32_t lowTime1NanoSeconds,
                                     int32_t* status) {}
 
 void HAL_SetAddressableLEDSyncTime(HAL_AddressableLEDHandle handle,
diff --git a/hal/src/main/native/sim/CANAPI.cpp b/hal/src/main/native/sim/CANAPI.cpp
index 38014bd..0eae18a 100644
--- a/hal/src/main/native/sim/CANAPI.cpp
+++ b/hal/src/main/native/sim/CANAPI.cpp
@@ -35,13 +35,6 @@
 static UnlimitedHandleResource<HAL_CANHandle, CANStorage, HAL_HandleEnum::CAN>*
     canHandles;
 
-static uint32_t GetPacketBaseTime() {
-  int status = 0;
-  auto basetime = HAL_GetFPGATime(&status);
-  // us to ms
-  return (basetime / 1000ull) & 0xFFFFFFFF;
-}
-
 namespace hal {
 namespace init {
 void InitializeCANAPI() {
@@ -71,6 +64,13 @@
   return createdId;
 }
 
+uint32_t HAL_GetCANPacketBaseTime() {
+  int status = 0;
+  auto basetime = HAL_GetFPGATime(&status);
+  // us to ms
+  return (basetime / 1000ull) & 0xFFFFFFFF;
+}
+
 HAL_CANHandle HAL_InitializeCAN(HAL_CANManufacturer manufacturer,
                                 int32_t deviceId, HAL_CANDeviceType deviceType,
                                 int32_t* status) {
@@ -275,7 +275,7 @@
     auto i = can->receives.find(messageId);
     if (i != can->receives.end()) {
       // Found, check if new enough
-      uint32_t now = GetPacketBaseTime();
+      uint32_t now = HAL_GetCANPacketBaseTime();
       if (now - i->second.lastTimeStamp > static_cast<uint32_t>(timeoutMs)) {
         // Timeout, return bad status
         *status = HAL_CAN_TIMEOUT;
@@ -307,7 +307,7 @@
     auto i = can->receives.find(messageId);
     if (i != can->receives.end()) {
       // Found, check if new enough
-      uint32_t now = GetPacketBaseTime();
+      uint32_t now = HAL_GetCANPacketBaseTime();
       if (now - i->second.lastTimeStamp < static_cast<uint32_t>(periodMs)) {
         *status = 0;
         // Read the data from the stored message into the output
@@ -337,7 +337,7 @@
     auto i = can->receives.find(messageId);
     if (i != can->receives.end()) {
       // Found, check if new enough
-      uint32_t now = GetPacketBaseTime();
+      uint32_t now = HAL_GetCANPacketBaseTime();
       if (now - i->second.lastTimeStamp > static_cast<uint32_t>(timeoutMs)) {
         // Timeout, return bad status
         *status = HAL_CAN_TIMEOUT;
diff --git a/hal/src/main/native/sim/DIO.cpp b/hal/src/main/native/sim/DIO.cpp
index b611b35..f827bbf 100644
--- a/hal/src/main/native/sim/DIO.cpp
+++ b/hal/src/main/native/sim/DIO.cpp
@@ -127,9 +127,7 @@
   // higher freq.
   // TODO: Round in the linear rate domain.
   // uint8_t pwmPeriodPower = static_cast<uint8_t>(
-  //    std::log(1.0 / (kExpectedLoopTiming * 0.25E-6 * rate)) /
-  //        std::log(2.0) +
-  //    0.5);
+  //     std::log2(1.0 / (kExpectedLoopTiming * 0.25E-6 * rate)) + 0.5);
   // TODO(THAD) : Add a case to set this in the simulator
   // digitalSystem->writePWMPeriodPower(pwmPeriodPower, status);
 }
diff --git a/hal/src/main/native/sim/DigitalInternal.h b/hal/src/main/native/sim/DigitalInternal.h
index e7f531e..8fa679a 100644
--- a/hal/src/main/native/sim/DigitalInternal.h
+++ b/hal/src/main/native/sim/DigitalInternal.h
@@ -39,14 +39,6 @@
  * devices.
  */
 constexpr float kDefaultPwmPeriod = 5.05f;
-/**
- * kDefaultPwmCenter is the PWM range center in ms
- */
-constexpr float kDefaultPwmCenter = 1.5f;
-/**
- * kDefaultPWMStepsDown is the number of PWM steps below the centerpoint
- */
-constexpr int32_t kDefaultPwmStepsDown = 1000;
 constexpr int32_t kPwmDisabled = 0;
 
 struct DigitalPort {
diff --git a/hal/src/main/native/sim/DriverStation.cpp b/hal/src/main/native/sim/DriverStation.cpp
index c99493d..67b2eb7 100644
--- a/hal/src/main/native/sim/DriverStation.cpp
+++ b/hal/src/main/native/sim/DriverStation.cpp
@@ -75,7 +75,7 @@
 static JoystickDataCache caches[3];
 static JoystickDataCache* currentRead = &caches[0];
 static JoystickDataCache* currentReadLocal = &caches[0];
-static std::atomic<JoystickDataCache*> currentCache{&caches[1]};
+static std::atomic<JoystickDataCache*> currentCache{nullptr};
 static JoystickDataCache* lastGiven = &caches[1];
 static JoystickDataCache* cacheToUpdate = &caches[2];
 
@@ -194,7 +194,7 @@
 
 HAL_AllianceStationID HAL_GetAllianceStation(int32_t* status) {
   if (gShutdown) {
-    return HAL_AllianceStationID_kRed1;
+    return HAL_AllianceStationID_kUnknown;
   }
   std::scoped_lock lock{driverStation->cacheMutex};
   return currentRead->allianceStation;
@@ -318,9 +318,9 @@
   // TODO
 }
 
-void HAL_RefreshDSData(void) {
+HAL_Bool HAL_RefreshDSData(void) {
   if (gShutdown) {
-    return;
+    return false;
   }
   HAL_ControlWord controlWord;
   std::memset(&controlWord, 0, sizeof(controlWord));
@@ -336,6 +336,7 @@
     currentRead = prev;
   }
   newestControlWord = controlWord;
+  return prev != nullptr;
 }
 
 void HAL_ProvideNewDataEventHandle(WPI_EventHandle handle) {
diff --git a/hal/src/main/native/sim/Encoder.cpp b/hal/src/main/native/sim/Encoder.cpp
index 137ee78..964777d 100644
--- a/hal/src/main/native/sim/Encoder.cpp
+++ b/hal/src/main/native/sim/Encoder.cpp
@@ -363,7 +363,7 @@
     return 0.0;
   }
 
-  return encoder->distancePerPulse;
+  return SimEncoderData[encoder->index].distancePerPulse;
 }
 
 HAL_EncoderEncodingType HAL_GetEncoderEncodingType(
diff --git a/hal/src/main/native/sim/HAL.cpp b/hal/src/main/native/sim/HAL.cpp
index 82dd8c4..ce8b6dd 100644
--- a/hal/src/main/native/sim/HAL.cpp
+++ b/hal/src/main/native/sim/HAL.cpp
@@ -288,6 +288,10 @@
   return HALSIM_GetRoboRioComments(buffer, size);
 }
 
+int32_t HAL_GetTeamNumber(void) {
+  return HALSIM_GetRoboRioTeamNumber();
+}
+
 uint64_t HAL_GetFPGATime(int32_t* status) {
   return hal::GetFPGATime();
 }
@@ -328,6 +332,14 @@
   return false;  // Figure out if we need to detect a brownout condition
 }
 
+HAL_Bool HAL_GetRSLState(int32_t* status) {
+  return false;
+}
+
+HAL_Bool HAL_GetSystemTimeValid(int32_t* status) {
+  return true;
+}
+
 HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) {
   static std::atomic_bool initialized{false};
   static wpi::mutex initializeMutex;
diff --git a/hal/src/main/native/sim/Notifier.cpp b/hal/src/main/native/sim/Notifier.cpp
index c686eea..3d2c802 100644
--- a/hal/src/main/native/sim/Notifier.cpp
+++ b/hal/src/main/native/sim/Notifier.cpp
@@ -11,6 +11,7 @@
 #include <string>
 
 #include <wpi/SmallVector.h>
+#include <wpi/StringExtras.h>
 #include <wpi/condition_variable.h>
 #include <wpi/mutex.h>
 
@@ -316,8 +317,9 @@
     if (num < size) {
       arr[num].handle = handle;
       if (notifier->name.empty()) {
-        std::snprintf(arr[num].name, sizeof(arr[num].name), "Notifier%d",
-                      static_cast<int>(getHandleIndex(handle)));
+        wpi::format_to_n_c_str(arr[num].name, sizeof(arr[num].name),
+                               "Notifier{}",
+                               static_cast<int>(getHandleIndex(handle)));
       } else {
         std::strncpy(arr[num].name, notifier->name.c_str(),
                      sizeof(arr[num].name) - 1);
diff --git a/hal/src/main/native/sim/PWM.cpp b/hal/src/main/native/sim/PWM.cpp
index 698769f..c668039 100644
--- a/hal/src/main/native/sim/PWM.cpp
+++ b/hal/src/main/native/sim/PWM.cpp
@@ -4,6 +4,9 @@
 
 #include "hal/PWM.h"
 
+#include <algorithm>
+#include <cmath>
+
 #include "ConstantsInternal.h"
 #include "DigitalInternal.h"
 #include "HALInitializer.h"
@@ -18,6 +21,46 @@
 void InitializePWM() {}
 }  // namespace hal::init
 
+static inline int32_t GetMaxPositivePwm(DigitalPort* port) {
+  return port->maxPwm;
+}
+
+static inline int32_t GetMinPositivePwm(DigitalPort* port) {
+  if (port->eliminateDeadband) {
+    return port->deadbandMaxPwm;
+  } else {
+    return port->centerPwm + 1;
+  }
+}
+
+static inline int32_t GetCenterPwm(DigitalPort* port) {
+  return port->centerPwm;
+}
+
+static inline int32_t GetMaxNegativePwm(DigitalPort* port) {
+  if (port->eliminateDeadband) {
+    return port->deadbandMinPwm;
+  } else {
+    return port->centerPwm - 1;
+  }
+}
+
+static inline int32_t GetMinNegativePwm(DigitalPort* port) {
+  return port->minPwm;
+}
+
+static inline int32_t GetPositiveScaleFactor(DigitalPort* port) {
+  return GetMaxPositivePwm(port) - GetMinPositivePwm(port);
+}  ///< The scale for positive speeds.
+
+static inline int32_t GetNegativeScaleFactor(DigitalPort* port) {
+  return GetMaxNegativePwm(port) - GetMinNegativePwm(port);
+}  ///< The scale for negative speeds.
+
+static inline int32_t GetFullRangeScaleFactor(DigitalPort* port) {
+  return GetMaxPositivePwm(port) - GetMinNegativePwm(port);
+}  ///< The scale for positions.
+
 extern "C" {
 
 HAL_DigitalHandle HAL_InitializePWMPort(HAL_PortHandle portHandle,
@@ -62,7 +105,7 @@
   SimPWMData[origChannel].initialized = true;
 
   // Defaults to allow an always valid config.
-  HAL_SetPWMConfig(handle, 2.0, 1.501, 1.5, 1.499, 1.0, status);
+  HAL_SetPWMConfigMicroseconds(handle, 2000, 1501, 1500, 1499, 1000, status);
 
   port->previousAllocation = allocationLocation ? allocationLocation : "";
 
@@ -84,62 +127,28 @@
   return channel < kNumPWMChannels && channel >= 0;
 }
 
-void HAL_SetPWMConfig(HAL_DigitalHandle pwmPortHandle, double max,
-                      double deadbandMax, double center, double deadbandMin,
-                      double min, int32_t* status) {
+void HAL_SetPWMConfigMicroseconds(HAL_DigitalHandle pwmPortHandle, int32_t max,
+                                  int32_t deadbandMax, int32_t center,
+                                  int32_t deadbandMin, int32_t min,
+                                  int32_t* status) {
   auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
   if (port == nullptr) {
     *status = HAL_HANDLE_ERROR;
     return;
   }
 
-  // calculate the loop time in milliseconds
-  double loopTime =
-      HAL_GetPWMLoopTiming(status) / (kSystemClockTicksPerMicrosecond * 1e3);
-  if (*status != 0) {
-    return;
-  }
-
-  int32_t maxPwm = static_cast<int32_t>((max - kDefaultPwmCenter) / loopTime +
-                                        kDefaultPwmStepsDown - 1);
-  int32_t deadbandMaxPwm = static_cast<int32_t>(
-      (deadbandMax - kDefaultPwmCenter) / loopTime + kDefaultPwmStepsDown - 1);
-  int32_t centerPwm = static_cast<int32_t>(
-      (center - kDefaultPwmCenter) / loopTime + kDefaultPwmStepsDown - 1);
-  int32_t deadbandMinPwm = static_cast<int32_t>(
-      (deadbandMin - kDefaultPwmCenter) / loopTime + kDefaultPwmStepsDown - 1);
-  int32_t minPwm = static_cast<int32_t>((min - kDefaultPwmCenter) / loopTime +
-                                        kDefaultPwmStepsDown - 1);
-
-  port->maxPwm = maxPwm;
-  port->deadbandMaxPwm = deadbandMaxPwm;
-  port->deadbandMinPwm = deadbandMinPwm;
-  port->centerPwm = centerPwm;
-  port->minPwm = minPwm;
+  port->maxPwm = max;
+  port->deadbandMaxPwm = deadbandMax;
+  port->deadbandMinPwm = deadbandMin;
+  port->centerPwm = center;
+  port->minPwm = min;
   port->configSet = true;
 }
 
-void HAL_SetPWMConfigRaw(HAL_DigitalHandle pwmPortHandle, int32_t maxPwm,
-                         int32_t deadbandMaxPwm, int32_t centerPwm,
-                         int32_t deadbandMinPwm, int32_t minPwm,
-                         int32_t* status) {
-  auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
-  if (port == nullptr) {
-    *status = HAL_HANDLE_ERROR;
-    return;
-  }
-
-  port->maxPwm = maxPwm;
-  port->deadbandMaxPwm = deadbandMaxPwm;
-  port->deadbandMinPwm = deadbandMinPwm;
-  port->centerPwm = centerPwm;
-  port->minPwm = minPwm;
-}
-
-void HAL_GetPWMConfigRaw(HAL_DigitalHandle pwmPortHandle, int32_t* maxPwm,
-                         int32_t* deadbandMaxPwm, int32_t* centerPwm,
-                         int32_t* deadbandMinPwm, int32_t* minPwm,
-                         int32_t* status) {
+void HAL_GetPWMConfigMicroseconds(HAL_DigitalHandle pwmPortHandle,
+                                  int32_t* maxPwm, int32_t* deadbandMaxPwm,
+                                  int32_t* centerPwm, int32_t* deadbandMinPwm,
+                                  int32_t* minPwm, int32_t* status) {
   auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
   if (port == nullptr) {
     *status = HAL_HANDLE_ERROR;
@@ -172,15 +181,49 @@
   return port->eliminateDeadband;
 }
 
-void HAL_SetPWMRaw(HAL_DigitalHandle pwmPortHandle, int32_t value,
-                   int32_t* status) {
+void HAL_SetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
+                                     int32_t value, int32_t* status) {
   auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
   if (port == nullptr) {
     *status = HAL_HANDLE_ERROR;
     return;
   }
 
-  SimPWMData[port->channel].rawValue = value;
+  SimPWMData[port->channel].pulseMicrosecond = value;
+
+  DigitalPort* dPort = port.get();
+  double speed = 0.0;
+
+  if (value == kPwmDisabled) {
+    speed = 0.0;
+  } else if (value > GetMaxPositivePwm(dPort)) {
+    speed = 1.0;
+  } else if (value < GetMinNegativePwm(dPort)) {
+    speed = -1.0;
+  } else if (value > GetMinPositivePwm(dPort)) {
+    speed = static_cast<double>(value - GetMinPositivePwm(dPort)) /
+            static_cast<double>(GetPositiveScaleFactor(dPort));
+  } else if (value < GetMaxNegativePwm(dPort)) {
+    speed = static_cast<double>(value - GetMaxNegativePwm(dPort)) /
+            static_cast<double>(GetNegativeScaleFactor(dPort));
+  } else {
+    speed = 0.0;
+  }
+
+  SimPWMData[port->channel].speed = speed;
+
+  double pos = 0.0;
+
+  if (value < GetMinNegativePwm(dPort)) {
+    pos = 0.0;
+  } else if (value > GetMaxPositivePwm(dPort)) {
+    pos = 1.0;
+  } else {
+    pos = static_cast<double>(value - GetMinNegativePwm(dPort)) /
+          static_cast<double>(GetFullRangeScaleFactor(dPort));
+  }
+
+  SimPWMData[port->channel].position = pos;
 }
 
 void HAL_SetPWMSpeed(HAL_DigitalHandle pwmPortHandle, double speed,
@@ -195,13 +238,36 @@
     return;
   }
 
-  if (speed < -1.0) {
-    speed = -1.0;
-  } else if (speed > 1.0) {
-    speed = 1.0;
+  if (std::isfinite(speed)) {
+    speed = std::clamp(speed, -1.0, 1.0);
+  } else {
+    speed = 0.0;
   }
 
-  SimPWMData[port->channel].speed = speed;
+  DigitalPort* dPort = port.get();
+
+  // calculate the desired output pwm value by scaling the speed appropriately
+  int32_t rawValue;
+  if (speed == 0.0) {
+    rawValue = GetCenterPwm(dPort);
+  } else if (speed > 0.0) {
+    rawValue =
+        std::lround(speed * static_cast<double>(GetPositiveScaleFactor(dPort)) +
+                    static_cast<double>(GetMinPositivePwm(dPort)));
+  } else {
+    rawValue =
+        std::lround(speed * static_cast<double>(GetNegativeScaleFactor(dPort)) +
+                    static_cast<double>(GetMaxNegativePwm(dPort)));
+  }
+
+  if (!((rawValue >= GetMinNegativePwm(dPort)) &&
+        (rawValue <= GetMaxPositivePwm(dPort))) ||
+      rawValue == kPwmDisabled) {
+    *status = HAL_PWM_SCALE_ERROR;
+    return;
+  }
+
+  HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, rawValue, status);
 }
 
 void HAL_SetPWMPosition(HAL_DigitalHandle pwmPortHandle, double pos,
@@ -222,7 +288,20 @@
     pos = 1.0;
   }
 
-  SimPWMData[port->channel].position = pos;
+  DigitalPort* dPort = port.get();
+
+  // note, need to perform the multiplication below as floating point before
+  // converting to int
+  int32_t rawValue = static_cast<int32_t>(
+      (pos * static_cast<double>(GetFullRangeScaleFactor(dPort))) +
+      GetMinNegativePwm(dPort));
+
+  if (rawValue == kPwmDisabled) {
+    *status = HAL_PWM_SCALE_ERROR;
+    return;
+  }
+
+  HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, rawValue, status);
 }
 
 void HAL_SetPWMDisabled(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
@@ -231,19 +310,20 @@
     *status = HAL_HANDLE_ERROR;
     return;
   }
-  SimPWMData[port->channel].rawValue = 0;
+  SimPWMData[port->channel].pulseMicrosecond = 0;
   SimPWMData[port->channel].position = 0;
   SimPWMData[port->channel].speed = 0;
 }
 
-int32_t HAL_GetPWMRaw(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
+int32_t HAL_GetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
+                                        int32_t* status) {
   auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
   if (port == nullptr) {
     *status = HAL_HANDLE_ERROR;
     return 0;
   }
 
-  return SimPWMData[port->channel].rawValue;
+  return SimPWMData[port->channel].pulseMicrosecond;
 }
 
 double HAL_GetPWMSpeed(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
@@ -299,6 +379,19 @@
   SimPWMData[port->channel].zeroLatch = false;
 }
 
+void HAL_SetPWMAlwaysHighMode(HAL_DigitalHandle pwmPortHandle,
+                              int32_t* status) {
+  auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
+  if (port == nullptr) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  SimPWMData[port->channel].pulseMicrosecond = 0xFFFF;
+  SimPWMData[port->channel].position = 0xFFFF;
+  SimPWMData[port->channel].speed = 0xFFFF;
+}
+
 void HAL_SetPWMPeriodScale(HAL_DigitalHandle pwmPortHandle, int32_t squelchMask,
                            int32_t* status) {
   auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
diff --git a/hal/src/main/native/sim/Power.cpp b/hal/src/main/native/sim/Power.cpp
index 08d5638..1eca18f 100644
--- a/hal/src/main/native/sim/Power.cpp
+++ b/hal/src/main/native/sim/Power.cpp
@@ -32,6 +32,7 @@
 int32_t HAL_GetUserCurrentFaults6V(int32_t* status) {
   return SimRoboRioData->userFaults6V;
 }
+void HAL_SetUserRailEnabled6V(HAL_Bool enabled, int32_t* status) {}
 double HAL_GetUserVoltage5V(int32_t* status) {
   return SimRoboRioData->userVoltage5V;
 }
@@ -44,6 +45,7 @@
 int32_t HAL_GetUserCurrentFaults5V(int32_t* status) {
   return SimRoboRioData->userFaults5V;
 }
+void HAL_SetUserRailEnabled5V(HAL_Bool enabled, int32_t* status) {}
 double HAL_GetUserVoltage3V3(int32_t* status) {
   return SimRoboRioData->userVoltage3V3;
 }
@@ -56,10 +58,14 @@
 int32_t HAL_GetUserCurrentFaults3V3(int32_t* status) {
   return SimRoboRioData->userFaults3V3;
 }
+void HAL_SetUserRailEnabled3V3(HAL_Bool enabled, int32_t* status) {}
 void HAL_SetBrownoutVoltage(double voltage, int32_t* status) {
   SimRoboRioData->brownoutVoltage = voltage;
 }
 double HAL_GetBrownoutVoltage(int32_t* status) {
   return SimRoboRioData->brownoutVoltage;
 }
+double HAL_GetCPUTemp(int32_t* status) {
+  return SimRoboRioData->cpuTemp;
+}
 }  // extern "C"
diff --git a/hal/src/main/native/sim/REVPH.cpp b/hal/src/main/native/sim/REVPH.cpp
index 163ca9c..a9e96f1 100644
--- a/hal/src/main/native/sim/REVPH.cpp
+++ b/hal/src/main/native/sim/REVPH.cpp
@@ -201,7 +201,7 @@
 
   std::scoped_lock lock{pcm->lock};
   auto& data = SimREVPHData[pcm->module].solenoidOutput;
-  uint8_t ret = 0;
+  int32_t ret = 0;
   for (int i = 0; i < kNumREVPHChannels; i++) {
     ret |= (data[i] << i);
   }
diff --git a/hal/src/main/native/sim/SimDevice.cpp b/hal/src/main/native/sim/SimDevice.cpp
index b6c637c..48b755e 100644
--- a/hal/src/main/native/sim/SimDevice.cpp
+++ b/hal/src/main/native/sim/SimDevice.cpp
@@ -26,6 +26,10 @@
   SimSimDeviceData->FreeDevice(handle);
 }
 
+const char* HAL_GetSimDeviceName(HAL_SimDeviceHandle handle) {
+  return SimSimDeviceData->GetDeviceName(handle);
+}
+
 HAL_SimValueHandle HAL_CreateSimValue(HAL_SimDeviceHandle device,
                                       const char* name, int32_t direction,
                                       const struct HAL_Value* initialValue) {
diff --git a/hal/src/main/native/sim/mockdata/PWMData.cpp b/hal/src/main/native/sim/mockdata/PWMData.cpp
index a221d13..005d95d 100644
--- a/hal/src/main/native/sim/mockdata/PWMData.cpp
+++ b/hal/src/main/native/sim/mockdata/PWMData.cpp
@@ -17,7 +17,7 @@
 PWMData* hal::SimPWMData;
 void PWMData::ResetData() {
   initialized.Reset(false);
-  rawValue.Reset(0);
+  pulseMicrosecond.Reset(0);
   speed.Reset(0);
   position.Reset(0);
   periodScale.Reset(0);
@@ -34,7 +34,7 @@
                                LOWERNAME)
 
 DEFINE_CAPI(HAL_Bool, Initialized, initialized)
-DEFINE_CAPI(int32_t, RawValue, rawValue)
+DEFINE_CAPI(int32_t, PulseMicrosecond, pulseMicrosecond)
 DEFINE_CAPI(double, Speed, speed)
 DEFINE_CAPI(double, Position, position)
 DEFINE_CAPI(int32_t, PeriodScale, periodScale)
@@ -46,7 +46,7 @@
 void HALSIM_RegisterPWMAllCallbacks(int32_t index, HAL_NotifyCallback callback,
                                     void* param, HAL_Bool initialNotify) {
   REGISTER(initialized);
-  REGISTER(rawValue);
+  REGISTER(pulseMicrosecond);
   REGISTER(speed);
   REGISTER(position);
   REGISTER(periodScale);
diff --git a/hal/src/main/native/sim/mockdata/PWMDataInternal.h b/hal/src/main/native/sim/mockdata/PWMDataInternal.h
index 737ced6..dd31a2a 100644
--- a/hal/src/main/native/sim/mockdata/PWMDataInternal.h
+++ b/hal/src/main/native/sim/mockdata/PWMDataInternal.h
@@ -10,7 +10,7 @@
 namespace hal {
 class PWMData {
   HAL_SIMDATAVALUE_DEFINE_NAME(Initialized)
-  HAL_SIMDATAVALUE_DEFINE_NAME(RawValue)
+  HAL_SIMDATAVALUE_DEFINE_NAME(PulseMicrosecond)
   HAL_SIMDATAVALUE_DEFINE_NAME(Speed)
   HAL_SIMDATAVALUE_DEFINE_NAME(Position)
   HAL_SIMDATAVALUE_DEFINE_NAME(PeriodScale)
@@ -19,7 +19,8 @@
  public:
   SimDataValue<HAL_Bool, HAL_MakeBoolean, GetInitializedName> initialized{
       false};
-  SimDataValue<int32_t, HAL_MakeInt, GetRawValueName> rawValue{0};
+  SimDataValue<int32_t, HAL_MakeInt, GetPulseMicrosecondName> pulseMicrosecond{
+      0};
   SimDataValue<double, HAL_MakeDouble, GetSpeedName> speed{0};
   SimDataValue<double, HAL_MakeDouble, GetPositionName> position{0};
   SimDataValue<int32_t, HAL_MakeInt, GetPeriodScaleName> periodScale{0};
diff --git a/hal/src/main/native/sim/mockdata/RoboRioData.cpp b/hal/src/main/native/sim/mockdata/RoboRioData.cpp
index b73b0d9..9a9a1a1 100644
--- a/hal/src/main/native/sim/mockdata/RoboRioData.cpp
+++ b/hal/src/main/native/sim/mockdata/RoboRioData.cpp
@@ -32,6 +32,8 @@
   userFaults5V.Reset(0);
   userFaults3V3.Reset(0);
   brownoutVoltage.Reset(6.75);
+  cpuTemp.Reset(45.0);
+  teamNumber.Reset(0);
   m_serialNumber = "";
   m_comments = "";
 }
@@ -132,6 +134,8 @@
 DEFINE_CAPI(int32_t, UserFaults5V, userFaults5V)
 DEFINE_CAPI(int32_t, UserFaults3V3, userFaults3V3)
 DEFINE_CAPI(double, BrownoutVoltage, brownoutVoltage)
+DEFINE_CAPI(double, CPUTemp, cpuTemp)
+DEFINE_CAPI(int32_t, TeamNumber, teamNumber)
 
 int32_t HALSIM_RegisterRoboRioSerialNumberCallback(
     HAL_RoboRioStringCallback callback, void* param, HAL_Bool initialNotify) {
@@ -187,5 +191,6 @@
   REGISTER(userFaults5V);
   REGISTER(userFaults3V3);
   REGISTER(brownoutVoltage);
+  REGISTER(cpuTemp);
 }
 }  // extern "C"
diff --git a/hal/src/main/native/sim/mockdata/RoboRioDataInternal.h b/hal/src/main/native/sim/mockdata/RoboRioDataInternal.h
index c3ff17a..aef61be 100644
--- a/hal/src/main/native/sim/mockdata/RoboRioDataInternal.h
+++ b/hal/src/main/native/sim/mockdata/RoboRioDataInternal.h
@@ -30,6 +30,8 @@
   HAL_SIMDATAVALUE_DEFINE_NAME(UserFaults5V)
   HAL_SIMDATAVALUE_DEFINE_NAME(UserFaults3V3)
   HAL_SIMDATAVALUE_DEFINE_NAME(BrownoutVoltage)
+  HAL_SIMDATAVALUE_DEFINE_NAME(CPUTemp)
+  HAL_SIMDATAVALUE_DEFINE_NAME(TeamNumber)
 
   HAL_SIMCALLBACKREGISTRY_DEFINE_NAME(SerialNumber)
   HAL_SIMCALLBACKREGISTRY_DEFINE_NAME(Comments);
@@ -57,6 +59,8 @@
   SimDataValue<int32_t, HAL_MakeInt, GetUserFaults3V3Name> userFaults3V3{0};
   SimDataValue<double, HAL_MakeDouble, GetBrownoutVoltageName> brownoutVoltage{
       6.75};
+  SimDataValue<double, HAL_MakeDouble, GetCPUTempName> cpuTemp{45.0};
+  SimDataValue<int32_t, HAL_MakeInt, GetTeamNumberName> teamNumber{0};
 
   int32_t RegisterSerialNumberCallback(HAL_RoboRioStringCallback callback,
                                        void* param, HAL_Bool initialNotify);
diff --git a/hal/src/test/native/cpp/HALTest.cpp b/hal/src/test/native/cpp/HALTest.cpp
index 62a4f85..0c4939e 100644
--- a/hal/src/test/native/cpp/HALTest.cpp
+++ b/hal/src/test/native/cpp/HALTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/HAL.h"
 
 namespace hal {
diff --git a/hal/src/test/native/cpp/can/CANTest.cpp b/hal/src/test/native/cpp/can/CANTest.cpp
index db9dbf5..72a81cd 100644
--- a/hal/src/test/native/cpp/can/CANTest.cpp
+++ b/hal/src/test/native/cpp/can/CANTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/CANAPI.h"
 #include "hal/HAL.h"
 #include "hal/simulation/CanData.h"
diff --git a/hal/src/test/native/cpp/handles/HandleTest.cpp b/hal/src/test/native/cpp/handles/HandleTest.cpp
index 5c98f7f..d230a06 100644
--- a/hal/src/test/native/cpp/handles/HandleTest.cpp
+++ b/hal/src/test/native/cpp/handles/HandleTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/HAL.h"
 #include "hal/handles/IndexedClassedHandleResource.h"
 
diff --git a/hal/src/test/native/cpp/main.cpp b/hal/src/test/native/cpp/main.cpp
index 7981c04..20ccbad 100644
--- a/hal/src/test/native/cpp/main.cpp
+++ b/hal/src/test/native/cpp/main.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/HAL.h"
 
 int main(int argc, char** argv) {
diff --git a/hal/src/test/native/cpp/mockdata/AnalogInDataTest.cpp b/hal/src/test/native/cpp/mockdata/AnalogInDataTest.cpp
index 284ebd6..e823375 100644
--- a/hal/src/test/native/cpp/mockdata/AnalogInDataTest.cpp
+++ b/hal/src/test/native/cpp/mockdata/AnalogInDataTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/AnalogInput.h"
 #include "hal/HAL.h"
 #include "hal/handles/HandlesInternal.h"
diff --git a/hal/src/test/native/cpp/mockdata/AnalogOutDataTest.cpp b/hal/src/test/native/cpp/mockdata/AnalogOutDataTest.cpp
index 15a5fa6..11dad05 100644
--- a/hal/src/test/native/cpp/mockdata/AnalogOutDataTest.cpp
+++ b/hal/src/test/native/cpp/mockdata/AnalogOutDataTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/AnalogOutput.h"
 #include "hal/HAL.h"
 #include "hal/handles/HandlesInternal.h"
diff --git a/hal/src/test/native/cpp/mockdata/DIODataTest.cpp b/hal/src/test/native/cpp/mockdata/DIODataTest.cpp
index e8ab350..35bfac5 100644
--- a/hal/src/test/native/cpp/mockdata/DIODataTest.cpp
+++ b/hal/src/test/native/cpp/mockdata/DIODataTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/DIO.h"
 #include "hal/HAL.h"
 #include "hal/handles/HandlesInternal.h"
diff --git a/hal/src/test/native/cpp/mockdata/DriverStationDataTest.cpp b/hal/src/test/native/cpp/mockdata/DriverStationDataTest.cpp
index 59658cb..ffab223 100644
--- a/hal/src/test/native/cpp/mockdata/DriverStationDataTest.cpp
+++ b/hal/src/test/native/cpp/mockdata/DriverStationDataTest.cpp
@@ -4,7 +4,9 @@
 
 #include <cstring>
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+#include <wpi/StringExtras.h>
+
 #include "hal/HAL.h"
 #include "hal/simulation/DriverStationData.h"
 
@@ -116,13 +118,12 @@
 }
 
 TEST(DriverStationTest, EventInfo) {
-  std::string eventName = "UnitTest";
-  std::string gameData = "Insert game specific info here :D";
+  constexpr std::string_view eventName = "UnitTest";
+  constexpr std::string_view gameData = "Insert game specific info here :D";
   HAL_MatchInfo info;
-  std::snprintf(info.eventName, sizeof(info.eventName), "%s",
-                eventName.c_str());
-  std::snprintf(reinterpret_cast<char*>(info.gameSpecificMessage),
-                sizeof(info.gameSpecificMessage), "%s", gameData.c_str());
+  wpi::format_to_n_c_str(info.eventName, sizeof(info.eventName), eventName);
+  wpi::format_to_n_c_str(reinterpret_cast<char*>(info.gameSpecificMessage),
+                         sizeof(info.gameSpecificMessage), gameData);
   info.gameSpecificMessageSize = gameData.size();
   info.matchNumber = 5;
   info.matchType = HAL_MatchType::HAL_kMatchType_qualification;
@@ -135,7 +136,7 @@
   std::string gsm{reinterpret_cast<char*>(dataBack.gameSpecificMessage),
                   dataBack.gameSpecificMessageSize};
 
-  EXPECT_STREQ(eventName.c_str(), dataBack.eventName);
+  EXPECT_EQ(eventName, dataBack.eventName);
   EXPECT_EQ(gameData, gsm);
   EXPECT_EQ(5, dataBack.matchNumber);
   EXPECT_EQ(HAL_MatchType::HAL_kMatchType_qualification, dataBack.matchType);
diff --git a/hal/src/test/native/cpp/mockdata/I2CDataTest.cpp b/hal/src/test/native/cpp/mockdata/I2CDataTest.cpp
index 7678a4a..af4499b 100644
--- a/hal/src/test/native/cpp/mockdata/I2CDataTest.cpp
+++ b/hal/src/test/native/cpp/mockdata/I2CDataTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/HAL.h"
 #include "hal/I2C.h"
 #include "hal/handles/HandlesInternal.h"
diff --git a/hal/src/test/native/cpp/mockdata/PCMDataTest.cpp b/hal/src/test/native/cpp/mockdata/PCMDataTest.cpp
index 58a94c0..70a36a9 100644
--- a/hal/src/test/native/cpp/mockdata/PCMDataTest.cpp
+++ b/hal/src/test/native/cpp/mockdata/PCMDataTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/CTREPCM.h"
 #include "hal/HAL.h"
 #include "hal/handles/HandlesInternal.h"
diff --git a/hal/src/test/native/cpp/mockdata/PDPDataTest.cpp b/hal/src/test/native/cpp/mockdata/PDPDataTest.cpp
index 59b3ea4..2e9977f 100644
--- a/hal/src/test/native/cpp/mockdata/PDPDataTest.cpp
+++ b/hal/src/test/native/cpp/mockdata/PDPDataTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/HAL.h"
 #include "hal/PowerDistribution.h"
 #include "hal/handles/HandlesInternal.h"
diff --git a/hal/src/test/native/cpp/mockdata/PWMDataTest.cpp b/hal/src/test/native/cpp/mockdata/PWMDataTest.cpp
index ab14704..b32e0a0 100644
--- a/hal/src/test/native/cpp/mockdata/PWMDataTest.cpp
+++ b/hal/src/test/native/cpp/mockdata/PWMDataTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/HAL.h"
 #include "hal/PWM.h"
 #include "hal/handles/HandlesInternal.h"
diff --git a/hal/src/test/native/cpp/mockdata/RelayDataTest.cpp b/hal/src/test/native/cpp/mockdata/RelayDataTest.cpp
index eef8631..e4017ca 100644
--- a/hal/src/test/native/cpp/mockdata/RelayDataTest.cpp
+++ b/hal/src/test/native/cpp/mockdata/RelayDataTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/HAL.h"
 #include "hal/Relay.h"
 #include "hal/handles/HandlesInternal.h"
diff --git a/hal/src/test/native/cpp/mockdata/SPIDataTest.cpp b/hal/src/test/native/cpp/mockdata/SPIDataTest.cpp
index c427eaf..1ae6260 100644
--- a/hal/src/test/native/cpp/mockdata/SPIDataTest.cpp
+++ b/hal/src/test/native/cpp/mockdata/SPIDataTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/HAL.h"
 #include "hal/SPI.h"
 #include "hal/handles/HandlesInternal.h"
diff --git a/hal/src/test/native/cpp/mockdata/SimDeviceDataTest.cpp b/hal/src/test/native/cpp/mockdata/SimDeviceDataTest.cpp
index 1203fd7..fef7ada 100644
--- a/hal/src/test/native/cpp/mockdata/SimDeviceDataTest.cpp
+++ b/hal/src/test/native/cpp/mockdata/SimDeviceDataTest.cpp
@@ -2,7 +2,8 @@
 // Open Source Software; you can modify and/or share it under the terms of
 // the WPILib BSD license file in the root directory of this project.
 
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+
 #include "hal/SimDevice.h"
 #include "hal/simulation/SimDeviceData.h"