Squashed 'third_party/allwpilib/' changes from 66b57f032..e473a00f9
e473a00f9 [wpiutil] Base64: Add unsigned span/vector variants (#3702)
52f2d580e [wpiutil] raw_uv_ostream: Add reset() (#3701)
d7b1e3576 [wpiutil] WebSocket: move std::function (#3700)
93799fbe9 [examples] Fix description of TrapezoidProfileSubsystem (#3699)
b84644740 [wpimath] Document pose estimator states, inputs, and outputs (#3698)
2dc35c139 [wpimath] Fix classpaths for JNI class loads (#3697)
2cb171f6f [docs] Set Doxygen extract_all to true and fix Doxygen failures (#3695)
a939cd9c8 [wpimath] Print uncontrollable/unobservable models in LQR and KF (#3694)
d5270d113 [wpimath] Clean up C++ StateSpaceUtil tests (#3692)
b20903960 [wpimath] Remove redundant discretization tests from StateSpaceUtilTest (#3689)
c0cb545b4 [wpilibc] Add deprecated Doxygen attribute to SpeedController (#3691)
35c9f66a7 [wpilib] Rename PneumaticsHub to PneumaticHub (#3686)
796d03d10 [wpiutil] Remove unused LLVM header (#3688)
8723caf78 [wpilibj] Make Java TrapezoidProfile.Constraints an immutable class (#3687)
187f50a34 [wpimath] Catch incorrect parameters to state-space models earlier (#3680)
8d04606c4 Replace instances of frc-characterization with SysId (NFC) (#3681)
b82d4f6e5 [hal, cscore, ntcore] Use WPI common handle type base
87e34967e [wpiutil] Add synchronization primitives
e32499c54 [wpiutil] Add ParallelTcpConnector (#3655)
aa0b49228 [wpilib] Remove redundant "quick turn" docs for curvature drive (NFC) (#3674)
57301a7f9 [hal] REVPH: Start closed-loop compressor control on init (#3673)
d1842ea8f [wpilib] Improve interrupt docs (NFC) (#3679)
558151061 [wpiutil] Add DsClient (#3654)
181723e57 Replace `.to<double>()` and `.template to<double>()` with `.value()` (#3667)
6bc1db44b [commands] Add pointer overload of AddRequirements (artf6003) (#3669)
737b57ed5 [wpimath] Update to drake v0.35.0 (#3665)
4d287d1ae [build] Upgrade WPIJREArtifact to JRE 2022-11.0.12u5 (#3666)
f26eb5ada [hal] Fix another typo (get -> gets) (NFC) (#3663)
94ed275ba [hal] Fix misspelling (numer -> number) (NFC) (#3662)
ac2f44da3 [wpiutil] uv: use move for std::function (#3653)
75fa1fbfb [wpiutil] json::serializer: Optimize construction (#3647)
5e689faea [wpiutil] Import MessagePack implementation (mpack) (#3650)
649a50b40 [wpiutil] Add LEB128 byte-by-byte reader (#3652)
e94397a97 [wpiutil] Move json_serializer.h to public headers (#3646)
4ec58724d [wpiutil] uv::Tcp: Clarify SetNoDelay documentation (#3649)
8cb294aa4 [wpiutil] WebSocket: Make Shutdown() public (#3651)
2b3a9a52b [wpiutil] json: Fix map iterator key() for std::string_view (#3645)
138cbb94b [wpiutil] uv::Async: Add direct call for no-parameter specialization (#3648)
e56d6dea8 [ci] Update testbench pool image to ubuntu-latest (#3643)
43f30e44e [build] Enable comments in doxygen source files (#3644)
9e6db17ef [build] Enable doxygen preprocessor expansion of WPI_DEPRECATED (#3642)
0e631ad2f Add WPILib version to issue template (#3641)
6229d8d2f [build] Docs: set case_sense_names to false (#3392)
4647d09b5 [docs] Fix Doxygen warnings, add CI docs lint job (#3639)
4ad3a5402 [hal] Fix PWM allocation channel (#3637)
05e5feac4 [docs] Fix brownout docs (NFC) (#3638)
67df469c5 [examples] Remove old command-based templates and examples (#3263)
689e9ccfb [hal, wpilib] Add brownout voltage configuration (#3632)
9cd4bc407 [docs] Add useLocal to avoid using installer artifacts (#3634)
61996c2bb [cscore] Fix Java direct callback notifications (#3631)
6d3dd99eb [build] Update to newest native-utils (#3633)
f0b484892 [wpiutil] Fix StringMap iterator equality check (#3629)
8352cbb7a Update development build instructions for 2022 (#3616)
6da08b71d [examples] Fix Intermediate Vision Java Example description (#3628)
5d99059bf [wpiutil] Remove optional.h (#3627)
fa41b106a [glass, wpiutil] Add missing format args (#3626)
4e3fd7d42 [build] Enable Zc:__cplusplus for Windows (#3625)
791d8354d [build] Suppress deprecation/removal warnings for old commands (#3618)
10f19e6fc [hal, wpilib] Add REV PneumaticsHub (#3600)
4c61a1305 [ntcore] Revert to per-element copy for toNative() (#3621)
7b3f62244 [wpiutil] SendableRegistry: Print exception stacktrace (#3620)
d347928e4 [hal] Use better error for when console out is enabled while attempting to use onboard serial port (#3622)
cc31079a1 [hal] Use setcap instead of setuid for setting thread priorities (#3613)
4676648b7 [wpimath] Upgrade to Drake v0.34.0 (#3607)
c7594c911 [build] Allow building wpilibc in cmake without cscore and opencv (#3605)
173cb7359 [wpilib] Add TimesliceRobot (#3502)
af295879f [hal] Set error status for I2C port out of range (#3603)
95dd20a15 [build] Enable spotbugs (#3601)
b65fce86b [wpilib] Remove Timer lock in wpilibj and update docs (#3602)
3b8d3bbcb Remove unused and add missing deprecated.h includes (#3599)
f9e976467 [examples] Rename DriveTrain classes to Drivetrain (#3594)
118a27be2 [wpilib] Add Timer tests (#3595)
59c89428e [wpilib] Deprecate Timer::HasPeriodPassed() (#3598)
202ca5e78 Force C++17 in .clang-format (#3597)
d6f185d8e Rename tests for consistency (#3592)
54ca474db [ci] Enable asan and tsan in CI for tests that pass (#3591)
1ca383b23 Add Debouncer (#3590)
179fde3a7 [build] Update to 2022 native utils and gradle 7 (#3588)
50198ffcf [examples] Add Mechanism2d visualization to Elevator Sim (#3587)
a446c2559 [examples] Synchronize C++ and Java Mechanism2d examples (#3589)
a7fb83103 [ci] clang-tidy: Generate compilation commands DB with Gradle (#3585)
4f5e0c9f8 [examples] Update ArmSimulation example to use Mechanism2d (#3572)
8164b91dc [CI] Print CMake test output on failure (#3583)
4d5fca27e [wpilib] Impove Mechanism2D documentation (NFC) (#3584)
fe59e4b9f Make C++ test names more consistent (#3586)
5c8868549 [wpilibc] Fix C++ MechanisimRoot2D to use same NT entries as Java/Glass (#3582)
9359431ba [wpimath] Clean up Eigen usage
72716f51c [wpimath] Upgrade to Eigen 3.4
382deef75 [wpimath] Explicitly export wpimath symbols
161e21173 [ntcore] Match standard handle layout, only allow 16 instances (#3577)
263a24811 [wpimath] Use jinja for codegen (#3574)
725251d29 [wpilib] Increase tolerances of DifferentialDriveSimTest (#3581)
4dff87301 [wpimath] Make LinearFilter::Factorial() constexpr (#3579)
60ede67ab [hal, wpilib] Switch PCM to be a single object that is allowed to be duplicated (#3475)
906bfc846 [build] Add CMake build support for sanitizers (#3576)
0d4f08ad9 [hal] Simplify string copy of joystick name (#3575)
a52bf87b7 [wpiutil] Add Java function package (#3570)
40c7645d6 [wpiutil] UidVector: Return old object from erase() (#3571)
5b886a23f [wpiutil] jni_util: Add size, operator[] to JArrayRef (#3569)
65797caa7 [sim] Fix halsim_ds_socket stringop overflow warning from GCC 10 (#3568)
66abb3988 [hal] Update runtime enum to allow selecting roborio 2 (#3565)
95a12e0ee [hal] UidSetter: Don't revert euid if its already current value (#3566)
27951442b [wpimath] Use external Eigen headers only (#3564)
c42e053ae [docs] Update to doxygen 1.9.2 (#3562)
e7048c8c8 [docs] Disable doxygen linking for common words that are also classes (#3563)
d8e0b6c97 [wpilibj] Fix java async interrupts (#3559)
5e6c34c61 Update to 2022 roborio image (#3537)
828f073eb [wpiutil] Fix uv::Buffer memory leaks caught by asan (#3555)
2dd5701ac [cscore] Fix mutex use-after-free in cscore test (#3557)
531439198 [ntcore] Fix NetworkTables memory leaks caught by asan (#3556)
3d9a4d585 [wpilibc] Fix AnalogTriggerOutput memory leak reported by asan (#3554)
54eda5928 [wpiutil] Ignore ubsan vptr upcast warning in SendableHelper moves (#3553)
5a4f75c9f [wpilib] Replace Speed controller comments with motor controller (NFC) (#3551)
7810f665f [wpiutil] Fix bug in uleb128 (#3540)
697e2dd33 [wpilib] Fix errant jaguar reference in comments (NFC) (#3550)
936c64ff5 [docs] Enable -linksource for javadocs (#3549)
1ea654954 [build] Upgrade CMake build to googletest 1.11.0 (#3548)
32d9949e4 [wpimath] Move controller tests to wpimath (#3541)
01ba56a8a [hal] Replace strncpy with memcpy (#3539)
e109c4251 [build] Rename makeSim flag to forceGazebo to better describe what it does (#3535)
e4c709164 [docs] Use a doxygen theme and add logo (#3533)
960b6e589 [wpimath] Fix Javadoc warning (#3532)
82eef8d5e [hal] Remove over current fault HAL functions from REV PDH (#3526)
aa3848b2c [wpimath] Move RobotDriveBase::ApplyDeadband() to MathUtil (#3529)
3b5d0d141 [wpimath] Add LinearFilter::BackwardFiniteDifference() (#3528)
c8fc715fe [wpimath] Upgrade drake files to v0.33.0 (#3531)
e5fe3a8e1 [build] Treat javadoc warnings as errors in CI and fix warnings (#3530)
e0c6cd3dc [wpimath] Add an operator for composing two Transform2ds (#3527)
2edd510ab [sim] Add sim wrappers for sensors that use SimDevice (#3517)
2b3e2ebc1 [hal] Fix HAL Notifier thread priority setting (#3522)
ab4cb5932 [gitignore] Update gitignore to ignore bazel / clion files (#3524)
57c8615af [build] Generate spotless patch on failure (#3523)
b90317321 Replace std::cout and std::cerr with fmt::print() (#3519)
10cc8b89c [hal] [wpilib] Add initial support for the REV PDH (#3503)
5d9ae3cdb [hal] Set HAL Notifier thread as RT by default (#3482)
192d251ee [wpilibcIntegrationTests] Properly disable DMA integration tests (#3514)
031962608 [wpilib] Add PS4Controller, remove Hand from GenericHID/XboxController (#3345)
25f6f478a [wpilib] Rename DriverStation::IsOperatorControl() to IsTeleop() (#3505)
e80f09f84 [wpilibj] Add unit tests (#3501)
c159f91f0 [wpilib] Only read DS control word once in IterativeRobotBase (#3504)
eb790a74d Add rio development docs documenting myRobot deploy tasks (#3508)
e47451f5a [wpimath] Replace auto with Eigen types (#3511)
252b8c83b Remove Java formatting from build task in CI (#3507)
09666ff29 Shorten Gazebo CI build (#3506)
baf2e501d Update myRobot to use 2021 java (#3509)
5ac60f0a2 [wpilib] Remove IterativeRobotBase mode init prints (#3500)
fb2ee8ec3 [wpilib] Add TimedRobot functions for running code on mode exit (#3499)
94e0db796 [wpilibc] Add more unit tests (#3494)
b25324695 [wpilibj] Add units to parameter names (NFC) (#3497)
1ac73a247 [hal] Rename PowerDistributionPanel to PowerDistribution (#3466)
2014115bc [examples] frisbeebot: Fix typo and reflow comments (NFC) (#3498)
4a944dc39 [examples] Consistently use 0 for controller port (#3496)
3838cc4ec Use unicode characters in docs equations (#3487)
85748f2e6 [examples] Add C++ TankDrive example (#3493)
d7b8aa56d [wpilibj] Rename DriverStation In[Mode] functions to follow style guide (#3488)
16e096cf8 [build] Fix CMake Windows CI (#3490)
50af74c38 [wpimath] Clean up NumericalIntegration and add Discretization tests (#3489)
bfc209b12 Automate fmt update (#3486)
e7f9331e4 [build] Update to Doxygen 1.9.1 (#3008)
ab8e8aa2a [wpimath] Update drake with upstream (#3484)
1ef826d1d [wpimath] Fix IOException path in WPIMath JNI (#3485)
52bddaa97 [wpimath] Disable iostream support for units and enable fmtlib (#3481)
e4dc3908b [wpiutil] Upgrade to fmtlib 8.0.1 (#3483)
1daadb812 [wpimath] Implement Dormand-Prince integration method (#3476)
9c2723391 [cscore] Add [[nodiscard]] to GrabFrame functions (#3479)
7a8796414 [wpilib] Add Notifier integration tests (#3480)
f8f13c536 [wpilibcExamples] Prefix decimal numbers with 0 (#3478)
1adb69c0f [ntcore] Use "NetworkTables" instead of "Network Tables" in NT specs (#3477)
5f5830b96 Upload wpiformat diff if one exists (#3474)
9fb4f35bb [wpimath] Add tests for DARE overload with Q, R, and N matrices (#3472)
c002e6f92 Run wpiformat (#3473)
c154e5262 [wpilib] Make solenoids exclusive use, PCM act like old sendable compressor (#3464)
6ddef1cca [hal] JNI setDIO: use a boolean and not a short (#3469)
9d68d9582 Remove extra newlines after open curly braces (NFC) (#3471)
a4233e1a1 [wpimath] Add script for updating Drake (#3470)
39373c6d2 Update README.md for new GCC version requirement (#3467)
d29acc90a [wpigui] Add option to reset UI on exit (#3463)
a371235b0 [ntcore] Fix dangling pointer in logger (#3465)
53b4891a5 [wpilibcintegrationtests] Fix deprecated Preferences usage (#3461)
646ded912 [wpimath] Remove incorrect discretization in pose estimators (#3460)
ea0b8f48e Fix some deprecation warnings due to fmtlib upgrade (#3459)
2067d7e30 [wpilibjexamples] Add wpimathjni, wpiutiljni to library path (#3455)
866571ab4 [wpiutil] Upgrade to fmtlib 8.0.0 (#3457)
4e1fa0308 [build] Skip PDB copy on windows build servers (#3458)
b45572167 [build] Change CI back to 18.04 docker images (#3456)
57a160f1b [wpilibc] Fix LiveWindow deprecation warning in RobotBase skeleton template (#3454)
29ae8640d [HLT] Implement duty cycle cross connect tests (#3453)
ee6377e54 [HLT] Add relay and analog cross connects (#3452)
b0f1ae7ea [build] CMake: Build the HAL even if WITH_CSCORE=OFF (#3449)
7aae2b72d Replace std::to_string() with fmt::format() (#3451)
73fcbbd74 [HLT] Add relay digital cross connect tests (#3450)
e7bedde83 [HLT] Add PWM tests that use DMA as the back end (#3447)
7253edb1e [wpilibc] Timer: Fix deprecated warning (#3446)
efa28125c [wpilibc] Add message to RobotBase on how to read stacktrace (#3444)
9832fcfe1 [hal] Fix DIO direction getter (#3445)
49c71f9f2 [wpilibj] Clarify robot quit message (#3364)
791770cf6 [wpimath] Move controller from wpilibj to wpimath (#3439)
9ce9188ff [wpimath] Add ReportWarning to MathShared (#3441)
362066a9b [wpilib] Deprecate getInstance() in favor of static functions (#3440)
26ff9371d Initial commit of cross connect integration test project (#3434)
4a36f86c8 [hal] Add support for DMA to Java (#3158)
85144e47f [commands] Unbreak build (#3438)
b417d961e Split Sendable into NT and non-NT portions (#3432)
ef4ea84cb [commands] Change grouping decorator impl to flatten nested group structures (#3335)
b422665a3 [examples] Invert right side of drive subsystems (#3437)
186dadf14 [hal] Error if attempting to set DIO output on an input port (#3436)
04e64db94 Remove redundant C++ lambda parentheses (NFC) (#3433)
f60994ad2 [wpiutil] Rename Java package to edu.wpi.first.util (#3431)
cfa1ca96f [wpilibc] Make ShuffleboardValue non-copyable (#3430)
4d9ff7643 Fix documentation warnings generated by JavaDoc (NFC) (#3428)
9e1b7e046 [build] Fix clang-tidy and clang-format (#3429)
a77c6ff3a [build] Upgrade clang-format and clang-tidy (NFC) (#3422)
099fde97d [wpilib] Improve PDP comments (NFC) (#3427)
f8fc2463e [wpilibc, wpiutil] Clean up includes (NFC) (#3426)
e246b7884 [wpimath] Clean up member initialization in feedforward classes (#3425)
c1e128bd5 Disable frivolous PMD warnings and enable PMD in ntcore (#3419)
8284075ee Run "Lint and Format" CI job on push as well as pull request (#3412)
f7db09a12 [wpimath] Move C++ filters into filter folder to match Java (#3417)
f9c3d54bd [wpimath] Reset error covariance in pose estimator ResetPosition() (#3418)
0773f4033 [hal] Ensure HAL status variables are initialized to zero (#3421)
d068fb321 [build] Upgrade CI to use 20.04 docker images (#3420)
8d054c940 [wpiutil] Remove STLExtras.h
80f1d7921 [wpiutil] Split function_ref to a separate header
64f541325 Use wpi::span instead of wpi::ArrayRef across all libraries (#3414)
2abbbd9e7 [build] clang-tidy: Remove bugprone-exception-escape (#3415)
a5c471af7 [wpimath] Add LQR template specialization for 2x2 system
edd2f0232 [wpimath] Add DARE solver for Q, R, and N with LQR ctor overloads
b2c3b2dd8 Use std::string_view and fmtlib across all libraries (#3402)
4f1cecb8e [wpiutil] Remove Path.h (#3413)
b336eac34 [build] Publish halsim_ws_core to Maven
2a09f6fa4 [build] Also build sim modules as static libraries
0e702eb79 [hal] Add a unified PCM object (#3331)
dea841103 [wpimath] Add fmtlib formatter overloads for Eigen::Matrix and units (#3409)
82856cf81 [wpiutil] Improve wpi::circular_buffer iterators (#3410)
8aecda03e [wpilib] Fix a documentation typo (#3408)
5c817082a [wpilib] Remove InterruptableSensorBase and replace with interrupt classes (#2410)
15c521a7f [wpimath] Fix drivetrain system identification (#3406)
989de4a1b [build] Force all linker warnings to be fatal for rio builds (#3407)
d9eeb45b0 [wpilibc] Add units to Ultrasonic class API (#3403)
fe570e000 [wpiutil] Replace llvm filesystem with C++17 filesystem (#3401)
01dc0249d [wpimath] Move SlewRateLimiter from wpilib to wpimath (#3399)
93523d572 [wpilibc] Clean up integration tests (#3400)
4f7a4464d [wpiutil] Rewrite StringExtras for std::string_view (#3394)
e09293a15 [wpilibc] Transition C++ classes to units::second_t (#3396)
827b17a52 [build] Create run tasks for Glass and OutlineViewer (#3397)
a61037996 [wpiutil] Avoid MSVC warning on span include (#3393)
4e2c3051b [wpilibc] Use std::string_view instead of Twine (#3380)
50915cb7e [wpilibc] MotorSafety::GetDescription(): Return std::string (#3390)
f4e2d26d5 [wpilibc] Move NullDeleter from frc/Base.h to wpi/NullDeleter.h (#3387)
cb0051ae6 [wpilibc] SimDeviceSim: use fmtlib (#3389)
a238cec12 [wpiutil] Deprecate wpi::math constants in favor of wpi::numbers (#3383)
393bf23c0 [ntcore, cscore, wpiutil] Standardize template impl files on .inc extension (NFC) (#3124)
e7d9ba135 [sim] Disable flaky web server integration tests (#3388)
0a0003c11 [wpilibjExamples] Fix name of Java swerve drive pose estimator example (#3382)
7e1b27554 [wpilibc] Use default copies and moves when possible (#3381)
fb2a56e2d [wpilibc] Remove START_ROBOT_CLASS macro (#3384)
84218bfb4 [wpilibc] Remove frc namespace shim (#3385)
dd7824340 [wpilibc] Remove C++ compiler version static asserts (#3386)
484cf9c0e [wpimath] Suppress the -Wmaybe-uninitialized warning in Eigen (#3378)
a04d1b4f9 [wpilibc] DriverStation: Remove ReportError and ReportWarning
831c10bdf [wpilibc] Errors: Use fmtlib
87603e400 [wpiutil] Import fmtlib (#3375)
442621672 [wpiutil] Add ArrayRef/std::span/wpi::span implicit conversions
bc15b953b [wpiutil] Add std::span implementation
6d20b1204 [wpiutil] StringRef, Twine, raw_ostream: Add std::string_view support (#3373)
2385c2a43 [wpilibc] Remove Utility.h (#3376)
87384ea68 [wpilib] Fix PIDController continuous range error calculations (#3170)
04dae799a [wpimath] Add SimpleMotorFeedforward::Calculate(velocity, nextVelocity) overload (#3183)
0768c3903 [wpilib] DifferentialDrive: Remove right side inversion (#3340)
8dd8d4d2d [wpimath] Fix redundant nested math package introduced by #3316 (#3368)
49b06beed [examples] Add Field2d to RamseteController example (#3371)
4c562a445 [wpimath] Fix typo in comment of update_eigen.py (#3369)
fdbbf1188 [wpimath] Add script for updating Eigen
f1e64b349 [wpimath] Move Eigen unsupported folder into eigeninclude
224f3a05c [sim] Fix build error when building with GCC 11.1 (#3361)
ff56d6861 [wpilibj] Fix SpeedController deprecated warnings (#3360)
1873fbefb [examples] Fix Swerve and Mecanum examples (#3359)
80b479e50 [examples] Fix SwerveBot example to use unique encoder ports (#3358)
1f7c9adee [wpilibjExamples] Fix pose estimator examples (#3356)
9ebc3b058 [outlineviewer] Change default size to 600x400 (#3353)
e21b443a4 [build] Gradle: Make C++ examples runnable (#3348)
da590120c [wpilibj] Add MotorController.setVoltage default (#3347)
561d53885 [build] Update opencv to 4.5.2, imgui/implot to latest (#3344)
44ad67ca8 [wpilibj] Preferences: Add missing Deprecated annotation (#3343)
3fe8fc75a [wpilibc] Revert "Return reference from GetInstance" (#3342)
3cc2da332 Merge branch '2022'
a3cd90dd7 [wpimath] Fix classpath used by generate_numbers.py (#3339)
d6cfdd3ba [wpilib] Preferences: Deprecate Put* in favor of Set* (#3337)
ba08baabb [wpimath] Update Drake DARE solver to v0.29.0 (#3336)
497b712f6 [wpilib] Make IterativeRobotBase::m_period private with getter
f00dfed7a [wpilib] Remove IterativeRobot base class
3c0846168 [hal] Use last error reporting instead of PARAMETER_OUT_OF_RANGE (#3328)
5ef2b4fdc [wpilibj] Fix @deprecated warning for SerialPort constructor (#3329)
23d2326d1 [hal] Report previous allocation location for indexed resource duplicates (#3322)
e338f9f19 [build] Fix wpilibc runCpp task (#3327)
c8ff626fe [wpimath] Move Java classes to edu.wpi.first.math (#3316)
4e424d51f [wpilibj] DifferentialDrivetrainSim: Rename constants to match the style guide (#3312)
6b50323b0 [cscore] Use Lock2DSize if possible for Windows USB cameras (#3326)
65c148536 [wpilibc] Fix "control reaches end of non-void function" warning (#3324)
f99f62bee [wpiutil] uv Handle: Use malloc/free instead of new/delete (#3325)
365f5449c [wpimath] Fix MecanumDriveKinematics (#3266)
ff52f207c [glass, wpilib] Rewrite Mechanism2d (#3281)
ee0eed143 [wpimath] Add DCMotor factory function for Romi motors (#3319)
512738072 [hal] Add HAL_GetLastError to enable better error messages from HAL calls (#3320)
ced654880 [glass, outlineviewer] Update Mac icons to macOS 11 style (#3313)
936d3b9f8 [templates] Add Java template for educational robot (#3309)
6e31230ad [examples] Fix odometry update in SwerveControllerCommand example (#3310)
05ebe9318 Merge branch 'main' into 2022
aaf24e255 [wpilib] Fix initial heading behavior in HolonomicDriveController (#3290)
8d961dfd2 [wpilibc] Remove ErrorBase (#3306)
659b37ef9 [wpiutil] StackTrace: Include offset on Linux (#3305)
0abf6c904 [wpilib] Move motor controllers to motorcontrol package (#3302)
4630191fa [wpiutil] circular_buffer: Use value initialization instead of passing zero (#3303)
b7b178f49 [wpilib] Remove Potentiometer interface
687066af3 [wpilib] Remove GyroBase
6b168ab0c [wpilib] Remove PIDController, PIDOutput, PIDSource
948625de9 [wpimath] Document conversion from filter cutoff frequency to time constant (#3299)
3848eb8b1 [wpilibc] Fix flywhel -> flywheel typo in FlywheelSim (#3298)
3abe0b9d4 [cscore] Move java package to edu.wpi.first.cscore (#3294)
d7fabe81f [wpilib] Remove RobotDrive (#3295)
1dc81669c [wpilib] Remove GearTooth (#3293)
01d0e1260 [wpilib] Revert move of RomiGyro into main wpilibc/j (#3296)
397e569aa [ntcore] Remove "using wpi" from nt namespace
79267f9e6 [ntcore] Remove NetworkTable -> nt::NetworkTable shim
48ebe5736 [ntcore] Remove deprecated Java interfaces and classes
c2064c78b [ntcore] Remove deprecated ITable interfaces
36608a283 [ntcore] Remove deprecated C++ APIs
a1c87e1e1 [glass] LogView: Add "copy to clipboard" button (#3274)
fa7240a50 [wpimath] Fix typo in quintic spline basis matrix
ffb4d38e2 [wpimath] Add derivation for spline basis matrices
f57c188f2 [wpilib] Add AnalogEncoder(int) ctor (#3273)
8471c4fb2 [wpilib] FieldObject2d: Add setTrajectory() method (#3277)
c97acd18e [glass] Field2d enhancements (#3234)
ffb590bfc [wpilib] Fix Compressor sendable properties (#3269)
6137f98eb [hal] Rename SimValueCallback2 to SimValueCallback (#3212)
a6f653969 [hal] Move registerSimPeriodic functions to HAL package (#3211)
10c038d9b [glass] Plot: Fix window creation after removal (#3264)
2d2eaa3ef [wpigui] Ensure window will be initially visible (#3256)
4d28b1f0c [wpimath] Use JNI for trajectory serialization (#3257)
3de800a60 [wpimath] TrajectoryUtil.h: Comment formatting (NFC) (#3262)
eff592377 [glass] Plot: Don't overwrite series ID (#3260)
a79faace1 [wpilibc] Return reference from GetInstance (#3247)
9550777b9 [wpilib] PWMSpeedController: Use PWM by composition (#3248)
c8521a3c3 [glass] Plot: Set reasonable default window size (#3261)
d71eb2cf3 [glass] Plot: Show full source name as tooltip and in popup (#3255)
160fb740f [hal] Use std::lround() instead of adding 0.5 and truncating (#3012)
48e9f3951 [wpilibj] Remove wpilibj package CameraServer (#3213)
8afa596fd [wpilib] Remove deprecated Sendable functions and SendableBase (#3210)
d3e45c297 [wpimath] Make C++ geometry classes immutable (#3249)
2c98939c1 [glass] StringChooser: Don't call SameLine() at end
a18a7409f [glass] NTStringChooser: Clear value of deleted entries
2f19cf452 [glass] NetworkTablesHelper: listen to delete events
da96707dc Merge branch 'main' into 2022
c3a8bdc24 [build] Fix clang-tidy action (#3246)
21624ef27 Add ImGui OutlineViewer (#3220)
1032c9b91 [wpiutil] Unbreak wpi::Format on Windows (#3242)
2e07902d7 [glass] NTField2D: Fix name lookup (#3233)
6e23e1840 [wpilibc] Remove WPILib.h (#3235)
3e22e4506 [wpilib] Make KoP drivetrain simulation weight 60 lbs (#3228)
79d1bd6c8 [glass] NetworkTablesSetting: Allow disable of server option (#3227)
fe341a16f [examples] Use more logical elevator setpoints in GearsBot (#3198)
62abf46b3 [glass] NetworkTablesSettings: Don't block GUI (#3226)
a95a5e0d9 [glass] Move NetworkTablesSettings to libglassnt (#3224)
d6f6ceaba [build] Run Spotless formatter (NFC) (#3221)
0922f8af5 [commands] CommandScheduler.requiring(): Note return can be null (NFC) (#2934)
6812302ff [examples] Make DriveDistanceOffboard example work in sim (#3199)
f3f86b8e7 [wpimath] Add pose estimator overload for vision + std dev measurement (#3200)
1a2680b9e [wpilibj] Change CommandBase.withName() to return CommandBase (#3209)
435bbb6a8 [command] RamseteCommand: Output 0 if interrupted (#3216)
3cf44e0a5 [hal] Add function for changing HAL Notifier thread priority (#3218)
40b367513 [wpimath] Units.java: Add kg-lb conversions (#3203)
9f563d584 [glass] NT: Fix return value in StringToDoubleArray (#3208)
af4adf537 [glass] Auto-size plots to fit window (#3193)
2560146da [sim] GUI: Add option to show prefix in Other Devices (#3186)
eae3a6397 gitignore: Ignore .cache directory (#3196)
959611420 [wpilib] Require non-zero positive value for PIDController.period (#3175)
9522f2e8c [wpimath] Add methods to concatenate trajectories (#3139)
e42a0b6cf [wpimath] Rotation2d comment formatting (NFC) (#3162)
d1c7032de [wpimath] Fix order of setting gyro offset in pose estimators (#3176)
d241bc81a [sim] Add DoubleSolenoidSim and SolenoidSim classes (#3177)
cb7f39afa [wpilibc] Add RobotController::GetBatteryVoltage() to C++ (#3179)
99b5ad9eb [wpilibj] Fix warnings that are not unused variables or deprecation (#3161)
c14b23775 [build] Fixup doxygen generated include dirs to match what users would need (#3154)
d447c7dc3 [sim] Add SimDeviceSim ctor overloads (#3134)
247420c9c [build] Remove jcenter repo (#3157)
04b112e00 [build] Include debug info in plugin published artifacts (#3149)
be0ce9900 [examples] Use PWMSparkMax instead of PWMVictorSPX (#3156)
69e8d0b65 [wpilib] Move RomiGyro into main wpilibc/j (#3143)
94e685e1b [wpimath] Add custom residual support to EKF (#3148)
5899f3dd2 [sim] GUI: Make keyboard settings loading more robust (#3167)
f82aa1d56 [wpilib] Fix HolonomicDriveController atReference() behavior (#3163)
fe5c2cf4b [wpimath] Remove ControllerUtil.java (#3169)
43d40c6e9 [wpiutil] Suppress unchecked cast in CombinedRuntimeLoader (#3155)
3d44d8f79 [wpimath] Fix argument order in UKF docs (NFC) (#3147)
ba6fe8ff2 [cscore] Add USB camera change event (#3123)
533725888 [build] Tweak OpenCV cmake search paths to work better on Linux (#3144)
29bf9d6ef [cscore] Add polled support to listener
483beb636 [ntcore] Move CallbackManager to wpiutil
fdaec7759 [examples] Instantiate m_ramseteController in example (#3142)
8494a5761 Rename default branch to main (#3140)
45590eea2 [wpigui] Hardcode window scale to 1 on macOS (#3135)
834a64920 [build] Publish libglass and libglassnt to Maven (#3127)
2c2ccb361 [wpimath] Fix Rotation2d equality operator (#3128)
fb5c8c39a [wpigui] clang-tidy: readability-braces-around-statements
f7d39193a [wpigui] Fix copyright in pfd and wpigui_metal.mm
aec796b21 [ntcore] Fix conditional jump on uninitialized value (#3125)
fb13bb239 [sim] GUI: Add right click popup for keyboard joystick settings (#3119)
c517ec677 [build] Update thirdparty-imgui to 1.79-2 (#3118)
e8cbf2a71 [wpimath] Fix typo in SwerveDrivePoseEstimator doc (NFC) (#3112)
e9c86df46 [wpimath] Add tests for swerve module optimization (#3100)
6ba8c289c [examples] Remove negative of ArcadeDrive(fwd, ..) in the C++ Getting Started Example (#3102)
3f1672e89 [hal] Add SimDevice createInt() and createLong() (#3110)
15be5cbf1 [examples] Fix segfault in GearsBot C++ example (#3111)
4cf0e5e6d Add quick links to API documentation in README (#3082)
6b1898f12 Fix RT priority docs (NFC) (#3098)
b3426e9c0 [wpimath] Fix missing whitespace in pose estimator doc (#3097)
38c1a1f3e [examples] Fix feildRelative -> fieldRelative typo in XControllerCommand examples (#3104)
4488e25f1 [glass] Shorten SmartDashboard window names (#3096)
cfdb3058e [wpilibj] Update SimDeviceSimTest (#3095)
64adff5fe [examples] Fix typo in ArcadeDrive constructor parameter name (#3092)
6efc58e3d [build] Fix issues with build on windows, deprecations, and native utils (#3090)
f393989a5 [wpimath, wpiutil] Add wpi::array for compile time size checking (#3087)
d6ed20c1e [build] Set macOS deployment target to 10.14 (#3088)
7c524014c [hal] Add [[nodiscard]] to HAL_WaitForNotifierAlarm() (#3085)
406d055f0 [wpilib] Fixup wouldHitLowerLimit in elevator and arm simulation classes. (#3076)
04a90b5dd [examples] Don't continually set setpoint in PotentiometerPID Examples (#3084)
8c5bfa013 [sim] GUI: Add max value setting for keyboard joysticks (#3083)
bc80c5535 [hal] Add SimValue reset() function (#3064)
9c3b51ca0 [wpilib] Document simulation APIs (#3079)
26584ff14 [wpimath] Add model description to LinearSystemId Javadocs (#3080)
42c3d5286 [examples] Sync Java and C++ trajectories in sim example (#3081)
64e72f710 [wpilibc] Add missing function RoboRioSim::ResetData (#3073)
e95503798 [wpimath] Add optimize() to SwerveModuleState (#3065)
fb99910c2 [hal] Add SimInt and SimLong wrappers for int/long SimValue (#3066)
e620bd4d3 [doc] Add machine-readable websocket specification (#3059)
a44e761d9 [glass] Add support for plot Y axis labels
ea1974d57 [wpigui] Update imgui and implot to latest
85a0bd43c [wpimath] Add RKF45 integration (#3047)
278e0f126 [glass] Use .controllable to set widgets' read-only state (#3035)
d8652cfd4 [wpimath] Make Java DCMotor API consistent with C++ and fix motor calcs (#3046)
377b7065a [build] Add toggleOffOn to Java spotless (#3053)
1e9c79c58 [sim] Use plant output to retrieve simulated position (#3043)
78147aa34 [sim] GUI: Fix Keyboard Joystick (#3052)
cd4a2265b [ntcore] Fix NetworkTableEntry::GetRaw() (#3051)
767ac1de1 [build] Use deploy key for doc publish (#3048)
d762215d1 [build] Add publish documentation script (#3040)
1fd09593c [examples] Add missing TestInit method to GettingStarted Example (#3039)
e45a0f6ce [examples] Add RomiGyro to the Romi Reference example (#3037)
94f852572 Update imaging link and fix typo (#3038)
d73cf64e5 [examples] Update RomiReference to match motor directions (#3036)
f945462ba Bump copyright year to 2021 (#3033)
b05946175 [wpimath] Catch Drake JNI exceptions and rethrow them (#3032)
62f0f8190 [wpimath] Deduplicate angle modulus functions (#2998)
bf8c0da4b [glass] Add "About" popup with version number (#3031)
dfdd6b389 [build] Increase Gradle heap size in Gazebo build (#3028)
f5e0fc3e9 Finish clang-tidy cleanups (#3003)
d741101fe [sim] Revert accidental commit of WSProvider_PDP.h (#3027)
e1620799c [examples] Add C++ RomiReference example (#2969)
749c7adb1 [command] Fix use-after-free in CommandScheduler (#3024)
921a73391 [sim] Add WS providers for AddressableLED, PCM, and Solenoid (#3026)
26d0004fe [build] Split Actions into different yml files (#3025)
948af6d5b [wpilib] PWMSpeedController.get(): Apply Inversion (#3016)
670a187a3 [wpilibc] SuppliedValueWidget.h: Forward declare ShuffleboardContainer (#3021)
be9f72502 [ntcore] NetworkTableValue: Use std::forward instead of std::move (#3022)
daf3f4cb1 [cscore] cscore_raw_cv.h: Fix error in PutFrame() (#3019)
5acda4cc7 [wpimath] ElevatorFeedforward.h: Add time.h include
8452af606 [wpimath] units/radiation.h: Add mass.h include
630d44952 [hal] ErrorsInternal.h: Add stdint.h include
7372cf7d9 [cscore] Windows NetworkUtil.cpp: Add missing include
b7e46c558 Include .h from .inc/.inl files (NFC) (#3017)
bf8f8710e [examples] Update Romi template and example (#2996)
6ffe5b775 [glass] Ensure NetworkTableTree parent context menu has an id (#3015)
be0805b85 [build] Update to WPILibVersioningPlugin 4.1.0 (#3014)
65b2359b2 [build] Add spotless for other files (#3007)
8651aa73e [examples] Enable NT Flush in Field2d examples (#3013)
78b542737 [build] Add Gazebo build to Actions CI (#3004)
fccf86532 [sim] DriverStationGui: Fix two bugs (#3010)
185741760 [sim] WSProvider_Joystick: Fix off-by-1 in incoming buttons (#3011)
ee7114a58 [glass] Add drive class widgets (#2975)
00fa91d0d [glass] Use ImGui style for gyro widget colors (#3009)
b7a25bfc3 ThirdPartyNotices: Add portable file dialogs license (#3005)
a2e46b9a1 [glass] modernize-use-nullptr (NFC) (#3006)
a751fa22d [build] Apply spotless for java formatting (#1768)
e563a0b7d [wpimath] Make LinearSystemLoop move-constructible and move-assignable (#2967)
49085ca94 [glass] Add context menus to remove and add NetworkTables values (#2979)
560a850a2 [glass] Add NetworkTables Log window (#2997)
66782e231 [sim] Create Left/Right drivetrain current accessors (#3001)
b60eb1544 clang-tidy: bugprone-virtual-near-miss
cbe59fa3b clang-tidy: google-explicit-constructor
c97c6dc06 clang-tidy: google-readability-casting (NFC)
32fa97d68 clang-tidy: modernize-use-nullptr (NFC)
aee460326 clang-tidy: modernize-pass-by-value
29c7da5f1 clang-tidy: modernize-make-unique
6131f4e32 clang-tidy: modernize-concat-nested-namespaces (NFC)
67e03e625 clang-tidy: modernize-use-equals-default
b124f9101 clang-tidy: modernize-use-default-member-init
d11a3a638 clang-tidy: modernize-use-override (NFC)
4cc0706b0 clang-tidy: modernize-use-using (NFC)
885f5a978 [wpilibc] Speed up ScopedTracerTest (#2999)
60b596457 [wpilibj] Fix typos (NFC) (#3000)
6e1919414 [build] Bring naming checkstyle rules up to date with Google Style guide (#1781)
8c8ec5e63 [wpilibj] Suppress unchecked cast warnings (#2995)
b8413ddd5 [wpiutil] Add noexcept to timestamp static functions (#2994)
5d976b6e1 [glass] Load NetworkTableView settings on first draw (#2993)
2b4317452 Replace NOLINT(runtime/explicit) comments with NOLINT (NFC) (#2992)
1c3011ba4 [glass] Fix handling of "/" NetworkTables key (#2991)
574a42f3b [hal] Fix UnsafeManipulateDIO status check (#2987)
9005cd59e [wpilib] Clamp input voltage in sim classes (#2955)
dd494d4ab [glass] NetworkTablesModel::Update(): Avoid use-after-move (#2988)
7cca469a1 [wpimath] NormalizeAngle: Make inline, remove unnamed namespace (#2986)
2aed432b4 Add braces to C++ single-line loops and conditionals (NFC) (#2973)
0291a3ff5 [wpiutil] StringRef: Add noexcept to several constructors (#2984)
5d7315280 [wpimath] Update UnitsTest.cpp copyright (#2985)
254931b9a [wpimath] Remove LinearSystem from LinearSystemLoop (#2968)
aa89744c9 Update OtherVersions.md to include wpimath info (#2983)
1cda3f5ad [glass] Fix styleguide (#2976)
8f1f64ffb Remove year from file copyright message (NFC) (#2972)
2bc0a7795 [examples] Fix wpiformat warning about utility include (#2971)
4204da6ad [glass] Add application icon
7ac39b10f [wpigui] Add icon support
6b567e006 [wpimath] Add support for varying vision standard deviations in pose estimators (#2956)
df299d6ed [wpimath] Add UnscentedKalmanFilter::Correct() overload (#2966)
4e34f0523 [examples] Use ADXRS450_GyroSim class in simulation example (#2964)
9962f6fd7 [wpilib] Give Field2d a default Sendable name (#2953)
f9d492f4b [sim] GUI: Show "Other Devices" window by default (#2961)
a8bb2ef1c [sim] Fix ADXRS450_GyroSim and DutyCycleEncoderSim (#2963)
240c629cd [sim] Try to guess "Map Gamepad" setting (#2960)
952567dd3 [wpilibc] Add missing move constructors and assignment operators (#2959)
10b396b4c [sim] Various WebSockets fixes and enhancements (#2952)
699bbe21a [examples] Fix comments in Gearsbot to match implementation (NFC) (#2957)
27b67deca [glass] Add more widgets (#2947)
581b7ec55 [wpilib] Add option to flush NetworkTables every iterative loop
acfbb1a44 [ntcore] DispatcherBase::Flush: Use wpi::Now()
d85a6d8fe [ntcore] Reduce limit on flush and update rate to 5 ms
20fbb5c63 [sim] Fix stringop truncation warning from GCC 10 (#2945)
1051a06a7 [glass] Show NT timestamps in seconds (#2944)
98dfc2620 [glass] Fix plots (#2943)
1ba0a2ced [sim] GUI: Add keyboard virtual joystick support (#2940)
4afb13f98 [examples] Replace M_PI with wpi::math::pi (#2938)
b27d33675 [examples] Enhance Romi templates (#2931)
00b9ae77f [sim] Change default WS port number to 3300 (#2932)
65219f309 [examples] Update Field2d position in periodic() (#2928)
f78d1d434 [sim] Process WS Encoder reset internally (#2927)
941edca59 [hal] Add Java SimDeviceDataJNI.getSimDeviceName (#2924)
a699435ed [wpilibj] Fix FlywheelSim argument order in constructor (#2922)
66d641718 [examples] Add tasks to run Java examples (#2920)
558e37c41 [examples] Add simple differential drive simulation example (#2918)
4f40d991e [glass] Switch name of Glass back to glass (#2919)
549af9900 [build] Update native-utils to 2021.0.6 (#2914)
b33693009 [glass] Change basename of glass to Glass (#2915)
c9a0edfb8 [glass] Package macOS application bundle
2c5668af4 [wpigui] Add platform-specific preferences save
751dea32a [wpilibc] Try to work around ABI break introduced in #2901 (#2917)
cd8f4bfb1 [build] Package up msvc runtime into maven artifact (#2913)
a6cfcc686 [wpilibc] Move SendableChooser Doxygen comments to header (NFC) (#2911)
b8c4f603d [wpimath] Upgrade to Eigen 3.3.9 (#2910)
0075e4b39 [wpilibj] Fix NPE in Field2d (#2909)
125af556c [simulation] Fix halsim_gui ntcore and wpiutil deps (#2908)
963ad5c25 [wpilib] Add noise to Differential Drive simulator (#2903)
387f56cb7 [examples] Add Romi reference Java example and templates (#2905)
b3deda38c [examples] Zero motors on disabledInit() in sim physics examples (#2906)
2a5ca7745 [glass] Add glass: an application for display of robot data
727940d84 [wpilib] Move Field2d to SmartDashboard
8cd42478e [wpilib] SendableBuilder: Make GetTable() visible
c11d34b26 [command] Use addCommands in command group templates (#2900)
339d7445b [sim] Add HAL hooks for simulationPeriodic (#2881)
d16f05f2c [wpilib] Fix SmartDashboard update order (#2896)
5427b32a4 [wpiutil] unique_function: Restrict implicit conversion (#2899)
f73701239 [ntcore] Add missing SetDefault initializer_list functions (#2898)
f5a6fc070 [sim] Add initialized flag for all solenoids on a PCM (#2897)
bdf5ba91a [wpilibj] Fix typo in ElevatorSim (#2895)
bc8f33877 [wpilib] Add pose estimators (#2867)
3413bfc06 [wpilib] PIDController: Recompute the error in AtSetpoint() (#2822)
2056f0ce0 [wpilib] Fix bugs in Hatchbot examples (#2893)
5eb8cfd69 [wpilibc] Fix MatchDataSender (#2892)
e6a425448 [build] Delete test folders after tests execute (#2891)
d478ad00d [imgui] Allow usage of imgui_stdlib (#2889)
53eda861d [build] Add unit-testing infrastructure to examples (#2863)
cc1d86ba6 [sim] Add title to simulator GUI window (#2888)
f0528f00e [build] CMake: Use project-specific binary and source dirs (#2886)
5cd2ad124 [wpilibc] Add Color::operator!= (#2887)
6c00e7a90 [build] CI CMake: build with GUI enabled (#2884)
53170bbb5 Update roboRIO toolchain installation instructions (#2883)
467258e05 [sim] GUI: Add option to not zero disconnected joysticks (#2876)
129be23c9 Clarify JDK installation instructions in readme (#2882)
8e9290e86 [build] Add separate CMake setting for wpimath (#2885)
7cf5bebf8 [wpilibj] Cache NT writes from DriverStation (#2780)
f7f9087fb [command] Fix timing issue in RamseteCommand (#2871)
256e7904f [wpilibj] SimDeviceSim: Fix sim value changed callback (#2880)
c8ea1b6c3 [wpilib] Add function to adjust LQR controller gain for pure time delay (#2878)
2816b06c0 [sim] HAL_GetControlWord: Fully zero output (#2873)
4c695ea08 Add toolchain installation instructions to README (#2875)
a14d51806 [wpimath] DCMotor: fix doc typo (NFC) (#2868)
017097791 [build] CMake: build sim extensions as shared libs (#2866)
f61726b5a [build] Fix cmake-config files (#2865)
fc27fdac5 [wpilibc] Cache NT values from driver station (#2768)
47c59859e [sim] Make SimDevice callbacks synchronous (#2861)
6e76ab9c0 [build] Turn on WITH_GUI for Windows cmake CI
5f78b7670 [build] Set GLFW_INSTALL to OFF
5e0808c84 [wpigui] Fix Windows cmake build
508f05a47 [imgui] Fix typo in Windows CMake target sources
Change-Id: I1737b45965f31803a96676bedc7dc40e337aa321
git-subtree-dir: third_party/allwpilib
git-subtree-split: e473a00f9785f9949e5ced30901baeaf426d2fc9
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/hal/src/main/native/athena/Accelerometer.cpp b/hal/src/main/native/athena/Accelerometer.cpp
index bc4d502..73b1357 100644
--- a/hal/src/main/native/athena/Accelerometer.cpp
+++ b/hal/src/main/native/athena/Accelerometer.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/Accelerometer.h"
@@ -78,11 +75,9 @@
kReg_OffZ = 0x31
};
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeAccelerometer() {}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
namespace hal {
@@ -94,7 +89,7 @@
*/
static void initializeAccelerometer() {
hal::init::CheckInit();
- int32_t status;
+ int32_t status = 0;
if (!accel) {
accel.reset(tAccel::create(&status));
@@ -126,7 +121,8 @@
// Execute and wait until it's done (up to a millisecond)
initialTime = HAL_GetFPGATime(&status);
while (accel->readSTAT(&status) & 1) {
- if (HAL_GetFPGATime(&status) > initialTime + 1000) break;
+ if (HAL_GetFPGATime(&status) > initialTime + 1000)
+ break;
}
// Send a stop transmit/receive message with the data
@@ -137,7 +133,8 @@
// Execute and wait until it's done (up to a millisecond)
initialTime = HAL_GetFPGATime(&status);
while (accel->readSTAT(&status) & 1) {
- if (HAL_GetFPGATime(&status) > initialTime + 1000) break;
+ if (HAL_GetFPGATime(&status) > initialTime + 1000)
+ break;
}
}
@@ -154,7 +151,8 @@
// Execute and wait until it's done (up to a millisecond)
initialTime = HAL_GetFPGATime(&status);
while (accel->readSTAT(&status) & 1) {
- if (HAL_GetFPGATime(&status) > initialTime + 1000) break;
+ if (HAL_GetFPGATime(&status) > initialTime + 1000)
+ break;
}
// Receive a message with the data and stop
@@ -165,7 +163,8 @@
// Execute and wait until it's done (up to a millisecond)
initialTime = HAL_GetFPGATime(&status);
while (accel->readSTAT(&status) & 1) {
- if (HAL_GetFPGATime(&status) > initialTime + 1000) break;
+ if (HAL_GetFPGATime(&status) > initialTime + 1000)
+ break;
}
return accel->readDATI(&status);
diff --git a/hal/src/main/native/athena/AddressableLED.cpp b/hal/src/main/native/athena/AddressableLED.cpp
index 7334c99..74a323a 100644
--- a/hal/src/main/native/athena/AddressableLED.cpp
+++ b/hal/src/main/native/athena/AddressableLED.cpp
@@ -1,19 +1,18 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/AddressableLED.h"
#include <cstring>
#include <FRC_FPGA_ChipObject/fpgainterfacecapi/NiFpga_HMB.h>
+#include <fmt/format.h>
#include "ConstantsInternal.h"
#include "DigitalInternal.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/AddressableLEDTypes.h"
#include "hal/ChipObject.h"
@@ -35,8 +34,7 @@
HAL_AddressableLEDHandle, AddressableLED, kNumAddressableLEDs,
HAL_HandleEnum::AddressableLED>* addressableLEDHandles;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeAddressableLED() {
static LimitedHandleResource<HAL_AddressableLEDHandle, AddressableLED,
kNumAddressableLEDs,
@@ -44,8 +42,7 @@
alH;
addressableLEDHandles = &alH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
@@ -147,8 +144,13 @@
return;
}
- if (length > HAL_kAddressableLEDMaxLength) {
+ if (length > HAL_kAddressableLEDMaxLength || length < 0) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format(
+ "LED length must be less than or equal to {}. {} was requested",
+ HAL_kAddressableLEDMaxLength, length));
return;
}
@@ -178,8 +180,13 @@
return;
}
- if (length > led->stringLength) {
+ if (length > led->stringLength || length < 0) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format(
+ "Data length must be less than or equal to {}. {} was requested",
+ led->stringLength, length));
return;
}
diff --git a/hal/src/main/native/athena/AnalogAccumulator.cpp b/hal/src/main/native/athena/AnalogAccumulator.cpp
index 6664c52..7ff7d47 100644
--- a/hal/src/main/native/athena/AnalogAccumulator.cpp
+++ b/hal/src/main/native/athena/AnalogAccumulator.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/AnalogAccumulator.h"
@@ -12,11 +9,9 @@
using namespace hal;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeAnalogAccumulator() {}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
@@ -28,7 +23,8 @@
return false;
}
for (int32_t i = 0; i < kNumAccumulators; i++) {
- if (port->channel == kAccumulatorChannels[i]) return true;
+ if (port->channel == kAccumulatorChannels[i])
+ return true;
}
return false;
}
diff --git a/hal/src/main/native/athena/AnalogGyro.cpp b/hal/src/main/native/athena/AnalogGyro.cpp
index 12d688d..19f26dd 100644
--- a/hal/src/main/native/athena/AnalogGyro.cpp
+++ b/hal/src/main/native/athena/AnalogGyro.cpp
@@ -1,18 +1,17 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/AnalogGyro.h"
+#include <string>
#include <thread>
-#include <wpi/raw_ostream.h>
+#include <fmt/format.h>
#include "AnalogInternal.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "hal/AnalogAccumulator.h"
#include "hal/AnalogInput.h"
#include "hal/handles/IndexedHandleResource.h"
@@ -24,6 +23,7 @@
double voltsPerDegreePerSecond;
double offset;
int32_t center;
+ std::string previousAllocation;
};
} // namespace
@@ -39,54 +39,62 @@
static IndexedHandleResource<HAL_GyroHandle, AnalogGyro, kNumAccumulators,
HAL_HandleEnum::AnalogGyro>* analogGyroHandles;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeAnalogGyro() {
static IndexedHandleResource<HAL_GyroHandle, AnalogGyro, kNumAccumulators,
HAL_HandleEnum::AnalogGyro>
agHandles;
analogGyroHandles = &agHandles;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
static void Wait(double seconds) {
- if (seconds < 0.0) return;
+ if (seconds < 0.0) {
+ return;
+ }
std::this_thread::sleep_for(std::chrono::duration<double>(seconds));
}
extern "C" {
HAL_GyroHandle HAL_InitializeAnalogGyro(HAL_AnalogInputHandle analogHandle,
+ const char* allocationLocation,
int32_t* status) {
hal::init::CheckInit();
+ // Handle will be type checked by HAL_IsAccumulatorChannel
+ int16_t channel = getHandleIndex(analogHandle);
if (!HAL_IsAccumulatorChannel(analogHandle, status)) {
if (*status == 0) {
*status = HAL_INVALID_ACCUMULATOR_CHANNEL;
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Analog Gyro",
+ 0, kNumAccumulators, channel);
}
return HAL_kInvalidHandle;
}
- // handle known to be correct, so no need to type check
- int16_t channel = getHandleIndex(analogHandle);
+ HAL_GyroHandle handle;
+ auto gyro = analogGyroHandles->Allocate(channel, &handle, status);
- auto handle = analogGyroHandles->Allocate(channel, status);
-
- if (*status != 0)
+ if (*status != 0) {
+ if (gyro) {
+ hal::SetLastErrorPreviouslyAllocated(status, "Analog Gyro", channel,
+ gyro->previousAllocation);
+ } else {
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Analog Gyro",
+ 0, kNumAccumulators, channel);
+ }
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
+ }
// Initialize port structure
- auto gyro = analogGyroHandles->Get(handle);
- if (gyro == nullptr) { // would only error on thread issue
- *status = HAL_HANDLE_ERROR;
- return HAL_kInvalidHandle;
- }
gyro->handle = analogHandle;
gyro->voltsPerDegreePerSecond = 0;
gyro->offset = 0;
gyro->center = 0;
+ gyro->previousAllocation = allocationLocation ? allocationLocation : "";
+
return handle;
}
@@ -100,17 +108,25 @@
gyro->voltsPerDegreePerSecond = kDefaultVoltsPerDegreePerSecond;
HAL_SetAnalogAverageBits(gyro->handle, kAverageBits, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
HAL_SetAnalogOversampleBits(gyro->handle, kOversampleBits, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
double sampleRate =
kSamplesPerSecond * (1 << (kAverageBits + kOversampleBits));
HAL_SetAnalogSampleRate(sampleRate, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
Wait(0.1);
HAL_SetAnalogGyroDeadband(handle, 0.0, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
}
void HAL_FreeAnalogGyro(HAL_GyroHandle handle) {
@@ -151,14 +167,18 @@
return;
}
HAL_ResetAccumulator(gyro->handle, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
const double sampleTime = 1.0 / HAL_GetAnalogSampleRate(status);
const double overSamples =
1 << HAL_GetAnalogOversampleBits(gyro->handle, status);
const double averageSamples =
1 << HAL_GetAnalogAverageBits(gyro->handle, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
Wait(sampleTime * overSamples * averageSamples);
}
@@ -170,15 +190,19 @@
}
HAL_InitAccumulator(gyro->handle, status);
- if (*status != 0) return;
- wpi::outs() << "Calibrating analog gyro for " << kCalibrationSampleTime
- << " seconds." << '\n';
+ if (*status != 0) {
+ return;
+ }
+ fmt::print("Calibrating analog gyro for {} seconds.\n",
+ kCalibrationSampleTime);
Wait(kCalibrationSampleTime);
int64_t value;
int64_t count;
HAL_GetAccumulatorOutput(gyro->handle, &value, &count, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
gyro->center = static_cast<int32_t>(
static_cast<double>(value) / static_cast<double>(count) + 0.5);
@@ -186,7 +210,9 @@
gyro->offset = static_cast<double>(value) / static_cast<double>(count) -
static_cast<double>(gyro->center);
HAL_SetAccumulatorCenter(gyro->handle, gyro->center, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
HAL_ResetAnalogGyro(handle, status);
}
@@ -200,7 +226,9 @@
int32_t deadband = static_cast<int32_t>(
volts * 1e9 / HAL_GetAnalogLSBWeight(gyro->handle, status) *
(1 << HAL_GetAnalogOversampleBits(gyro->handle, status)));
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
HAL_SetAccumulatorDeadband(gyro->handle, deadband, status);
}
diff --git a/hal/src/main/native/athena/AnalogInput.cpp b/hal/src/main/native/athena/AnalogInput.cpp
index 1d502b9..6b3add1 100644
--- a/hal/src/main/native/athena/AnalogInput.cpp
+++ b/hal/src/main/native/athena/AnalogInput.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/AnalogInput.h"
@@ -12,44 +9,52 @@
#include "AnalogInternal.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/AnalogAccumulator.h"
#include "hal/handles/HandlesInternal.h"
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeAnalogInput() {}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
using namespace hal;
extern "C" {
-HAL_AnalogInputHandle HAL_InitializeAnalogInputPort(HAL_PortHandle portHandle,
- int32_t* status) {
+HAL_AnalogInputHandle HAL_InitializeAnalogInputPort(
+ HAL_PortHandle portHandle, const char* allocationLocation,
+ int32_t* status) {
hal::init::CheckInit();
initializeAnalog(status);
- if (*status != 0) return HAL_kInvalidHandle;
+ if (*status != 0) {
+ return HAL_kInvalidHandle;
+ }
int16_t channel = getPortHandleChannel(portHandle);
- if (channel == InvalidHandleIndex) {
- *status = PARAMETER_OUT_OF_RANGE;
+ if (channel == InvalidHandleIndex || channel >= kNumAnalogInputs) {
+ *status = RESOURCE_OUT_OF_RANGE;
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Analog Input",
+ 0, kNumAnalogInputs, channel);
return HAL_kInvalidHandle;
}
- HAL_AnalogInputHandle handle = analogInputHandles->Allocate(channel, status);
+ HAL_AnalogInputHandle handle;
+ auto analog_port = analogInputHandles->Allocate(channel, &handle, status);
- if (*status != 0)
+ if (*status != 0) {
+ if (analog_port) {
+ hal::SetLastErrorPreviouslyAllocated(status, "Analog Input", channel,
+ analog_port->previousAllocation);
+ } else {
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Analog Input",
+ 0, kNumAnalogInputs, channel);
+ }
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
+ }
// Initialize port structure
- auto analog_port = analogInputHandles->Get(handle);
- if (analog_port == nullptr) { // would only error on thread issue
- *status = HAL_HANDLE_ERROR;
- return HAL_kInvalidHandle;
- }
analog_port->channel = static_cast<uint8_t>(channel);
if (HAL_IsAccumulatorChannel(handle, status)) {
analog_port->accumulator.reset(tAccumulator::create(channel, status));
@@ -61,6 +66,8 @@
analogInputSystem->writeScanList(channel, channel, status);
HAL_SetAnalogAverageBits(handle, kDefaultAverageBits, status);
HAL_SetAnalogOversampleBits(handle, kDefaultOversampleBits, status);
+ analog_port->previousAllocation =
+ allocationLocation ? allocationLocation : "";
return handle;
}
@@ -69,7 +76,9 @@
analogInputHandles->Free(analogPortHandle);
}
-HAL_Bool HAL_CheckAnalogModule(int32_t module) { return module == 1; }
+HAL_Bool HAL_CheckAnalogModule(int32_t module) {
+ return module == 1;
+}
HAL_Bool HAL_CheckAnalogInputChannel(int32_t channel) {
return channel < kNumAnalogInputs && channel >= 0;
@@ -83,13 +92,17 @@
// TODO: Need double comparison with epsilon.
// wpi_assert(!sampleRateSet || GetSampleRate() == samplesPerSecond);
initializeAnalog(status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
setAnalogSampleRate(samplesPerSecond, status);
}
double HAL_GetAnalogSampleRate(int32_t* status) {
initializeAnalog(status);
- if (*status != 0) return 0;
+ if (*status != 0) {
+ return 0;
+ }
uint32_t ticksPerConversion = analogInputSystem->readLoopTiming(status);
uint32_t ticksPerSample =
ticksPerConversion * getAnalogNumActiveChannels(status);
diff --git a/hal/src/main/native/athena/AnalogInternal.cpp b/hal/src/main/native/athena/AnalogInternal.cpp
index 6ac16b8..7ae6adc 100644
--- a/hal/src/main/native/athena/AnalogInternal.cpp
+++ b/hal/src/main/native/athena/AnalogInternal.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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 "AnalogInternal.h"
@@ -43,9 +40,13 @@
void initializeAnalog(int32_t* status) {
hal::init::CheckInit();
- if (analogSystemInitialized) return;
+ if (analogSystemInitialized) {
+ return;
+ }
std::scoped_lock lock(analogRegisterWindowMutex);
- if (analogSystemInitialized) return;
+ if (analogSystemInitialized) {
+ return;
+ }
analogInputSystem.reset(tAI::create(status));
analogOutputSystem.reset(tAO::create(status));
setAnalogNumChannelsToActivate(kNumAnalogInputs);
@@ -55,7 +56,9 @@
int32_t getAnalogNumActiveChannels(int32_t* status) {
int32_t scanSize = analogInputSystem->readConfig_ScanSize(status);
- if (scanSize == 0) return 8;
+ if (scanSize == 0) {
+ return 8;
+ }
return scanSize;
}
@@ -64,8 +67,9 @@
}
int32_t getAnalogNumChannelsToActivate(int32_t* status) {
- if (analogNumChannelsToActivate == 0)
+ if (analogNumChannelsToActivate == 0) {
return getAnalogNumActiveChannels(status);
+ }
return analogNumChannelsToActivate;
}
@@ -82,7 +86,9 @@
ticksPerSample / getAnalogNumChannelsToActivate(status);
// ticksPerConversion must be at least 80
if (ticksPerConversion < 80) {
- if ((*status) >= 0) *status = SAMPLE_RATE_TOO_HIGH;
+ if ((*status) >= 0) {
+ *status = SAMPLE_RATE_TOO_HIGH;
+ }
ticksPerConversion = 80;
}
diff --git a/hal/src/main/native/athena/AnalogInternal.h b/hal/src/main/native/athena/AnalogInternal.h
index a74562f..431c624 100644
--- a/hal/src/main/native/athena/AnalogInternal.h
+++ b/hal/src/main/native/athena/AnalogInternal.h
@@ -1,15 +1,13 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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>
#include <memory>
+#include <string>
#include <wpi/mutex.h>
@@ -34,6 +32,7 @@
struct AnalogPort {
uint8_t channel;
std::unique_ptr<tAccumulator> accumulator;
+ std::string previousAllocation;
};
extern IndexedHandleResource<HAL_AnalogInputHandle, hal::AnalogPort,
diff --git a/hal/src/main/native/athena/AnalogOutput.cpp b/hal/src/main/native/athena/AnalogOutput.cpp
index 77f841b..eab7d82 100644
--- a/hal/src/main/native/athena/AnalogOutput.cpp
+++ b/hal/src/main/native/athena/AnalogOutput.cpp
@@ -1,14 +1,14 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/AnalogOutput.h"
+#include <string>
+
#include "AnalogInternal.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/Errors.h"
#include "hal/handles/HandlesInternal.h"
@@ -20,6 +20,7 @@
struct AnalogOutput {
uint8_t channel;
+ std::string previousAllocation;
};
} // namespace
@@ -28,45 +29,53 @@
kNumAnalogOutputs, HAL_HandleEnum::AnalogOutput>*
analogOutputHandles;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeAnalogOutput() {
static IndexedHandleResource<HAL_AnalogOutputHandle, AnalogOutput,
kNumAnalogOutputs, HAL_HandleEnum::AnalogOutput>
aoH;
analogOutputHandles = &aoH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
-HAL_AnalogOutputHandle HAL_InitializeAnalogOutputPort(HAL_PortHandle portHandle,
- int32_t* status) {
+HAL_AnalogOutputHandle HAL_InitializeAnalogOutputPort(
+ HAL_PortHandle portHandle, const char* allocationLocation,
+ int32_t* status) {
hal::init::CheckInit();
initializeAnalog(status);
- if (*status != 0) return HAL_kInvalidHandle;
-
- int16_t channel = getPortHandleChannel(portHandle);
- if (channel == InvalidHandleIndex) {
- *status = PARAMETER_OUT_OF_RANGE;
+ if (*status != 0) {
return HAL_kInvalidHandle;
}
- HAL_AnalogOutputHandle handle =
- analogOutputHandles->Allocate(channel, status);
-
- if (*status != 0)
- return HAL_kInvalidHandle; // failed to allocate. Pass error back.
-
- auto port = analogOutputHandles->Get(handle);
- if (port == nullptr) { // would only error on thread issue
- *status = HAL_HANDLE_ERROR;
+ int16_t channel = getPortHandleChannel(portHandle);
+ if (channel == InvalidHandleIndex || channel >= kNumAnalogOutputs) {
+ *status = RESOURCE_OUT_OF_RANGE;
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Analog Output",
+ 0, kNumAnalogOutputs, channel);
return HAL_kInvalidHandle;
}
+ HAL_AnalogOutputHandle handle;
+ auto port = analogOutputHandles->Allocate(channel, &handle, status);
+
+ if (*status != 0) {
+ if (port) {
+ hal::SetLastErrorPreviouslyAllocated(status, "Analog Output", channel,
+ port->previousAllocation);
+ } else {
+ hal::SetLastErrorIndexOutOfRange(status,
+ "Invalid Index for Analog Output", 0,
+ kNumAnalogOutputs, channel);
+ }
+ return HAL_kInvalidHandle; // failed to allocate. Pass error back.
+ }
+
port->channel = static_cast<uint8_t>(channel);
+ port->previousAllocation = allocationLocation ? allocationLocation : "";
+
return handle;
}
@@ -85,10 +94,11 @@
uint16_t rawValue = static_cast<uint16_t>(voltage / 5.0 * 0x1000);
- if (voltage < 0.0)
+ if (voltage < 0.0) {
rawValue = 0;
- else if (voltage > 5.0)
+ } else if (voltage > 5.0) {
rawValue = 0x1000;
+ }
analogOutputSystem->writeMXP(port->channel, rawValue, status);
}
diff --git a/hal/src/main/native/athena/AnalogTrigger.cpp b/hal/src/main/native/athena/AnalogTrigger.cpp
index 9ec3f29..d9e2b92 100644
--- a/hal/src/main/native/athena/AnalogTrigger.cpp
+++ b/hal/src/main/native/athena/AnalogTrigger.cpp
@@ -1,15 +1,13 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/AnalogTrigger.h"
#include "AnalogInternal.h"
#include "DutyCycleInternal.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/AnalogInput.h"
#include "hal/DutyCycle.h"
@@ -33,8 +31,7 @@
kNumAnalogTriggers, HAL_HandleEnum::AnalogTrigger>*
analogTriggerHandles;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeAnalogTrigger() {
static LimitedHandleResource<HAL_AnalogTriggerHandle, AnalogTrigger,
kNumAnalogTriggers,
@@ -42,8 +39,7 @@
atH;
analogTriggerHandles = &atH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
@@ -143,6 +139,11 @@
if (lower < 0.0 || upper > 1.0) {
*status = PARAMETER_OUT_OF_RANGE;
+ auto lowerStr = std::to_string(lower);
+ auto upperStr = std::to_string(upper);
+ hal::SetLastError(
+ status, "Lower must be >= 0 and upper must be <=1. Requested lower " +
+ lowerStr + " Requested upper " + upperStr);
return;
}
diff --git a/hal/src/main/native/athena/CAN.cpp b/hal/src/main/native/athena/CAN.cpp
index 8105358..3436a0b 100644
--- a/hal/src/main/native/athena/CAN.cpp
+++ b/hal/src/main/native/athena/CAN.cpp
@@ -1,19 +1,14 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/CAN.h"
#include <FRC_NetworkCommunication/CANSessionMux.h>
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeCAN() {}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
diff --git a/hal/src/main/native/athena/CANAPI.cpp b/hal/src/main/native/athena/CANAPI.cpp
index d460885..a7c5b37 100644
--- a/hal/src/main/native/athena/CANAPI.cpp
+++ b/hal/src/main/native/athena/CANAPI.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/CANAPI.h"
@@ -47,15 +44,13 @@
return ms & 0xFFFFFFFF;
}
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeCANAPI() {
static UnlimitedHandleResource<HAL_CANHandle, CANStorage, HAL_HandleEnum::CAN>
cH;
canHandles = &cH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
static int32_t CreateCANId(CANStorage* storage, int32_t apiId) {
int32_t createdId = 0;
diff --git a/hal/src/main/native/athena/CTREPCM.cpp b/hal/src/main/native/athena/CTREPCM.cpp
new file mode 100644
index 0000000..b000ace
--- /dev/null
+++ b/hal/src/main/native/athena/CTREPCM.cpp
@@ -0,0 +1,399 @@
+// 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/CTREPCM.h"
+
+#include <fmt/format.h>
+
+#include "HALInitializer.h"
+#include "HALInternal.h"
+#include "PortsInternal.h"
+#include "hal/CANAPI.h"
+#include "hal/Errors.h"
+#include "hal/handles/IndexedHandleResource.h"
+
+using namespace hal;
+
+static constexpr HAL_CANManufacturer manufacturer =
+ HAL_CANManufacturer::HAL_CAN_Man_kCTRE;
+
+static constexpr HAL_CANDeviceType deviceType =
+ HAL_CANDeviceType::HAL_CAN_Dev_kPneumatics;
+
+static constexpr int32_t Status1 = 0x50;
+static constexpr int32_t StatusSolFaults = 0x51;
+static constexpr int32_t StatusDebug = 0x52;
+
+static constexpr int32_t Control1 = 0x70;
+static constexpr int32_t Control2 = 0x71;
+static constexpr int32_t Control3 = 0x72;
+
+static constexpr int32_t TimeoutMs = 100;
+static constexpr int32_t SendPeriod = 20;
+
+union PcmStatus {
+ uint8_t data[8];
+ struct Bits {
+ /* Byte 0 */
+ unsigned SolenoidBits : 8;
+ /* Byte 1 */
+ unsigned compressorOn : 1;
+ unsigned stickyFaultFuseTripped : 1;
+ unsigned stickyFaultCompCurrentTooHigh : 1;
+ unsigned faultFuseTripped : 1;
+ unsigned faultCompCurrentTooHigh : 1;
+ unsigned faultHardwareFailure : 1;
+ unsigned isCloseloopEnabled : 1;
+ unsigned pressureSwitchEn : 1;
+ /* Byte 2*/
+ unsigned battVoltage : 8;
+ /* Byte 3 */
+ unsigned solenoidVoltageTop8 : 8;
+ /* Byte 4 */
+ unsigned compressorCurrentTop6 : 6;
+ unsigned solenoidVoltageBtm2 : 2;
+ /* Byte 5 */
+ unsigned StickyFault_dItooHigh : 1;
+ unsigned Fault_dItooHigh : 1;
+ unsigned moduleEnabled : 1;
+ unsigned closedLoopOutput : 1;
+ unsigned compressorCurrentBtm4 : 4;
+ /* Byte 6 */
+ unsigned tokenSeedTop8 : 8;
+ /* Byte 7 */
+ unsigned tokenSeedBtm8 : 8;
+ } bits;
+};
+
+union PcmControl {
+ uint8_t data[8];
+ struct Bits {
+ /* Byte 0 */
+ unsigned tokenTop8 : 8;
+ /* Byte 1 */
+ unsigned tokenBtm8 : 8;
+ /* Byte 2 */
+ unsigned solenoidBits : 8;
+ /* Byte 3*/
+ unsigned reserved : 4;
+ unsigned closeLoopOutput : 1;
+ unsigned compressorOn : 1;
+ unsigned closedLoopEnable : 1;
+ unsigned clearStickyFaults : 1;
+ /* Byte 4 */
+ unsigned OneShotField_h8 : 8;
+ /* Byte 5 */
+ unsigned OneShotField_l8 : 8;
+ } bits;
+};
+
+struct PcmControlSetOneShotDur {
+ uint8_t sol10MsPerUnit[8];
+};
+
+union PcmStatusFault {
+ uint8_t data[8];
+ struct Bits {
+ /* Byte 0 */
+ unsigned SolenoidDisabledList : 8;
+ /* Byte 1 */
+ unsigned reserved_bit0 : 1;
+ unsigned reserved_bit1 : 1;
+ unsigned reserved_bit2 : 1;
+ unsigned reserved_bit3 : 1;
+ unsigned StickyFault_CompNoCurrent : 1;
+ unsigned Fault_CompNoCurrent : 1;
+ unsigned StickyFault_SolenoidJumper : 1;
+ unsigned Fault_SolenoidJumper : 1;
+ } bits;
+};
+
+union PcmDebug {
+ uint8_t data[8];
+ struct Bits {
+ unsigned tokFailsTop8 : 8;
+ unsigned tokFailsBtm8 : 8;
+ unsigned lastFailedTokTop8 : 8;
+ unsigned lastFailedTokBtm8 : 8;
+ unsigned tokSuccessTop8 : 8;
+ unsigned tokSuccessBtm8 : 8;
+ } bits;
+};
+
+namespace {
+struct PCM {
+ HAL_CANHandle canHandle;
+ wpi::mutex lock;
+ std::string previousAllocation;
+ PcmControl control;
+ PcmControlSetOneShotDur oneShot;
+};
+} // namespace
+
+static IndexedHandleResource<HAL_CTREPCMHandle, PCM, kNumCTREPCMModules,
+ HAL_HandleEnum::CTREPCM>* pcmHandles;
+
+namespace hal::init {
+void InitializeCTREPCM() {
+ static IndexedHandleResource<HAL_CTREPCMHandle, PCM, kNumCTREPCMModules,
+ HAL_HandleEnum::CTREPCM>
+ pH;
+ pcmHandles = &pH;
+}
+} // namespace hal::init
+
+#define READ_PACKET(type, frame, failureValue) \
+ auto pcm = pcmHandles->Get(handle); \
+ if (pcm == nullptr) { \
+ *status = HAL_HANDLE_ERROR; \
+ return failureValue; \
+ } \
+ type pcmStatus; \
+ int32_t length = 0; \
+ uint64_t receivedTimestamp = 0; \
+ HAL_ReadCANPacketTimeout(pcm->canHandle, frame, pcmStatus.data, &length, \
+ &receivedTimestamp, TimeoutMs, status); \
+ if (*status != 0) { \
+ return failureValue; \
+ }
+
+#define READ_STATUS(failureValue) READ_PACKET(PcmStatus, Status1, failureValue)
+#define READ_SOL_FAULTS(failureValue) \
+ READ_PACKET(PcmStatusFault, StatusSolFaults, failureValue)
+
+static void SendControl(PCM* pcm, int32_t* status) {
+ HAL_WriteCANPacketRepeating(pcm->canHandle, pcm->control.data, 8, Control1,
+ SendPeriod, status);
+}
+
+extern "C" {
+
+HAL_CTREPCMHandle HAL_InitializeCTREPCM(int32_t module,
+ const char* allocationLocation,
+ int32_t* status) {
+ hal::init::CheckInit();
+
+ HAL_CTREPCMHandle handle;
+ auto pcm = pcmHandles->Allocate(module, &handle, status);
+
+ if (*status != 0) {
+ if (pcm) {
+ hal::SetLastErrorPreviouslyAllocated(status, "CTRE PCM", module,
+ pcm->previousAllocation);
+ } else {
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for CTRE PCM", 0,
+ kNumCTREPCMModules, module);
+ }
+ return HAL_kInvalidHandle; // failed to allocate. Pass error back.
+ }
+
+ pcm->canHandle = HAL_InitializeCAN(manufacturer, module, deviceType, status);
+ if (*status != 0) {
+ pcmHandles->Free(handle);
+ return HAL_kInvalidHandle;
+ }
+
+ std::memset(&pcm->oneShot, 0, sizeof(pcm->oneShot));
+ std::memset(&pcm->control, 0, sizeof(pcm->control));
+
+ pcm->previousAllocation = allocationLocation ? allocationLocation : "";
+
+ // Enable closed loop control
+ HAL_SetCTREPCMClosedLoopControl(handle, true, status);
+ if (*status != 0) {
+ HAL_FreeCTREPCM(handle);
+ return HAL_kInvalidHandle;
+ }
+ return handle;
+}
+
+void HAL_FreeCTREPCM(HAL_CTREPCMHandle handle) {
+ auto pcm = pcmHandles->Get(handle);
+ if (pcm) {
+ HAL_CleanCAN(pcm->canHandle);
+ }
+ pcmHandles->Free(handle);
+}
+
+HAL_Bool HAL_CheckCTREPCMSolenoidChannel(int32_t channel) {
+ return channel < kNumCTRESolenoidChannels && channel >= 0;
+}
+
+HAL_Bool HAL_GetCTREPCMCompressor(HAL_CTREPCMHandle handle, int32_t* status) {
+ READ_STATUS(false);
+ return pcmStatus.bits.compressorOn;
+}
+
+void HAL_SetCTREPCMClosedLoopControl(HAL_CTREPCMHandle handle, HAL_Bool enabled,
+ int32_t* status) {
+ auto pcm = pcmHandles->Get(handle);
+ if (pcm == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
+ std::scoped_lock lock{pcm->lock};
+ pcm->control.bits.closedLoopEnable = enabled ? 1 : 0;
+ SendControl(pcm.get(), status);
+}
+
+HAL_Bool HAL_GetCTREPCMClosedLoopControl(HAL_CTREPCMHandle handle,
+ int32_t* status) {
+ READ_STATUS(false);
+ return pcmStatus.bits.isCloseloopEnabled;
+}
+
+HAL_Bool HAL_GetCTREPCMPressureSwitch(HAL_CTREPCMHandle handle,
+ int32_t* status) {
+ READ_STATUS(false);
+ return pcmStatus.bits.pressureSwitchEn;
+}
+
+double HAL_GetCTREPCMCompressorCurrent(HAL_CTREPCMHandle handle,
+ int32_t* status) {
+ READ_STATUS(0);
+ uint32_t result = pcmStatus.bits.compressorCurrentTop6;
+ result <<= 4;
+ result |= pcmStatus.bits.compressorCurrentBtm4;
+ return result * 0.03125; /* 5.5 fixed pt value in Amps */
+}
+
+HAL_Bool HAL_GetCTREPCMCompressorCurrentTooHighFault(HAL_CTREPCMHandle handle,
+ int32_t* status) {
+ READ_STATUS(false);
+ return pcmStatus.bits.faultCompCurrentTooHigh;
+}
+
+HAL_Bool HAL_GetCTREPCMCompressorCurrentTooHighStickyFault(
+ HAL_CTREPCMHandle handle, int32_t* status) {
+ READ_STATUS(false);
+ return pcmStatus.bits.stickyFaultCompCurrentTooHigh;
+}
+HAL_Bool HAL_GetCTREPCMCompressorShortedStickyFault(HAL_CTREPCMHandle handle,
+ int32_t* status) {
+ READ_STATUS(false);
+ return pcmStatus.bits.Fault_dItooHigh;
+}
+HAL_Bool HAL_GetCTREPCMCompressorShortedFault(HAL_CTREPCMHandle handle,
+ int32_t* status) {
+ READ_STATUS(false);
+ return pcmStatus.bits.StickyFault_dItooHigh;
+}
+HAL_Bool HAL_GetCTREPCMCompressorNotConnectedStickyFault(
+ HAL_CTREPCMHandle handle, int32_t* status) {
+ READ_SOL_FAULTS(false);
+ return pcmStatus.bits.StickyFault_CompNoCurrent;
+}
+HAL_Bool HAL_GetCTREPCMCompressorNotConnectedFault(HAL_CTREPCMHandle handle,
+ int32_t* status) {
+ READ_SOL_FAULTS(false);
+ return pcmStatus.bits.Fault_CompNoCurrent;
+}
+
+int32_t HAL_GetCTREPCMSolenoids(HAL_CTREPCMHandle handle, int32_t* status) {
+ READ_STATUS(0);
+ return pcmStatus.bits.SolenoidBits & 0xFF;
+}
+
+void HAL_SetCTREPCMSolenoids(HAL_CTREPCMHandle handle, int32_t mask,
+ int32_t values, int32_t* status) {
+ auto pcm = pcmHandles->Get(handle);
+ if (pcm == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
+ uint8_t smallMask = mask & 0xFF;
+ uint8_t smallValues =
+ (values & 0xFF) & smallMask; // Enforce only masked values are set
+ uint8_t invertMask = ~smallMask;
+
+ std::scoped_lock lock{pcm->lock};
+ uint8_t existingValue = invertMask & pcm->control.bits.solenoidBits;
+ pcm->control.bits.solenoidBits = existingValue | smallValues;
+ SendControl(pcm.get(), status);
+}
+
+int32_t HAL_GetCTREPCMSolenoidDisabledList(HAL_CTREPCMHandle handle,
+ int32_t* status) {
+ READ_SOL_FAULTS(0);
+ return pcmStatus.bits.SolenoidDisabledList;
+}
+
+HAL_Bool HAL_GetCTREPCMSolenoidVoltageStickyFault(HAL_CTREPCMHandle handle,
+ int32_t* status) {
+ READ_STATUS(false);
+ return pcmStatus.bits.stickyFaultFuseTripped;
+}
+
+HAL_Bool HAL_GetCTREPCMSolenoidVoltageFault(HAL_CTREPCMHandle handle,
+ int32_t* status) {
+ READ_STATUS(false);
+ return pcmStatus.bits.faultFuseTripped;
+}
+
+void HAL_ClearAllCTREPCMStickyFaults(HAL_CTREPCMHandle handle,
+ int32_t* status) {
+ uint8_t controlData[] = {0, 0, 0, 0x80};
+ HAL_WriteCANPacket(handle, controlData, sizeof(controlData), Control2,
+ status);
+}
+
+void HAL_FireCTREPCMOneShot(HAL_CTREPCMHandle handle, int32_t index,
+ int32_t* status) {
+ if (index > 7 || index < 0) {
+ *status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format("Only [0-7] are valid index values. Requested {}", index));
+ return;
+ }
+
+ auto pcm = pcmHandles->Get(handle);
+ if (pcm == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
+ std::scoped_lock lock{pcm->lock};
+ uint16_t oneShotField = pcm->control.bits.OneShotField_h8;
+ oneShotField <<= 8;
+ oneShotField |= pcm->control.bits.OneShotField_l8;
+
+ uint16_t shift = 2 * index;
+ uint16_t mask = 3;
+ uint8_t chBits = (oneShotField >> shift) & mask;
+ chBits = (chBits % 3) + 1;
+ oneShotField &= ~(mask << shift);
+ oneShotField |= (chBits << shift);
+ pcm->control.bits.OneShotField_h8 = oneShotField >> 8;
+ pcm->control.bits.OneShotField_l8 = oneShotField;
+ SendControl(pcm.get(), status);
+}
+
+void HAL_SetCTREPCMOneShotDuration(HAL_CTREPCMHandle handle, int32_t index,
+ int32_t durMs, int32_t* status) {
+ if (index > 7 || index < 0) {
+ *status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format("Only [0-7] are valid index values. Requested {}", index));
+ return;
+ }
+
+ auto pcm = pcmHandles->Get(handle);
+ if (pcm == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
+ std::scoped_lock lock{pcm->lock};
+ pcm->oneShot.sol10MsPerUnit[index] =
+ (std::min)(static_cast<uint32_t>(durMs) / 10,
+ static_cast<uint32_t>(0xFF));
+ HAL_WriteCANPacketRepeating(pcm->canHandle, pcm->oneShot.sol10MsPerUnit, 8,
+ Control2, SendPeriod, status);
+}
+
+} // extern "C"
diff --git a/hal/src/main/native/athena/PDP.cpp b/hal/src/main/native/athena/CTREPDP.cpp
similarity index 71%
rename from hal/src/main/native/athena/PDP.cpp
rename to hal/src/main/native/athena/CTREPDP.cpp
index f60e881..1a25a64 100644
--- a/hal/src/main/native/athena/PDP.cpp
+++ b/hal/src/main/native/athena/CTREPDP.cpp
@@ -1,18 +1,18 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/PDP.h"
+#include "CTREPDP.h"
+#include <fmt/format.h>
#include <wpi/mutex.h>
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/CANAPI.h"
#include "hal/Errors.h"
+#include "hal/handles/IndexedHandleResource.h"
using namespace hal;
@@ -103,72 +103,93 @@
} bits;
};
-static wpi::mutex pdpHandleMutex;
-static HAL_PDPHandle pdpHandles[kNumPDPModules];
+namespace {
+struct PDP {
+ HAL_CANHandle canHandle;
+ std::string previousAllocation;
+};
+} // namespace
-namespace hal {
-namespace init {
-void InitializePDP() {
- for (int i = 0; i < kNumPDPModules; i++) {
- pdpHandles[i] = HAL_kInvalidHandle;
- }
+static IndexedHandleResource<HAL_PDPHandle, PDP, kNumCTREPDPModules,
+ HAL_HandleEnum::CTREPDP>* pdpHandles;
+
+namespace hal::init {
+void InitializeCTREPDP() {
+ static IndexedHandleResource<HAL_PDPHandle, PDP, kNumCTREPDPModules,
+ HAL_HandleEnum::CTREPDP>
+ pH;
+ pdpHandles = &pH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
-HAL_PDPHandle HAL_InitializePDP(int32_t module, int32_t* status) {
+HAL_PDPHandle HAL_InitializePDP(int32_t module, const char* allocationLocation,
+ int32_t* status) {
hal::init::CheckInit();
if (!HAL_CheckPDPModule(module)) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status, fmt::format("Invalid pdp module {}", module));
return HAL_kInvalidHandle;
}
- std::scoped_lock lock(pdpHandleMutex);
-
- if (pdpHandles[module] != HAL_kInvalidHandle) {
- *status = 0;
- return pdpHandles[module];
- }
-
- auto handle = HAL_InitializeCAN(manufacturer, module, deviceType, status);
+ HAL_PDPHandle handle;
+ auto pdp = pdpHandles->Allocate(module, &handle, status);
if (*status != 0) {
- HAL_CleanCAN(handle);
+ if (pdp) {
+ hal::SetLastErrorPreviouslyAllocated(status, "CTRE PDP", module,
+ pdp->previousAllocation);
+ } else {
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for CTRE PDP", 0,
+ kNumCTREPDPModules, module);
+ }
+ return HAL_kInvalidHandle; // failed to allocate. Pass error back.
+ }
+
+ pdp->canHandle = HAL_InitializeCAN(manufacturer, module, deviceType, status);
+ if (*status != 0) {
+ pdpHandles->Free(handle);
return HAL_kInvalidHandle;
}
- pdpHandles[module] = handle;
+ pdp->previousAllocation = allocationLocation ? allocationLocation : "";
return handle;
}
void HAL_CleanPDP(HAL_PDPHandle handle) {
- HAL_CleanCAN(handle);
-
- for (int i = 0; i < kNumPDPModules; i++) {
- if (pdpHandles[i] == handle) {
- pdpHandles[i] = HAL_kInvalidHandle;
- return;
- }
+ auto pdp = pdpHandles->Get(handle);
+ if (pdp) {
+ HAL_CleanCAN(pdp->canHandle);
}
+ pdpHandles->Free(handle);
+}
+
+int32_t HAL_GetPDPModuleNumber(HAL_PDPHandle handle, int32_t* status) {
+ return hal::getHandleIndex(handle);
}
HAL_Bool HAL_CheckPDPModule(int32_t module) {
- return module < kNumPDPModules && module >= 0;
+ return module < kNumCTREPDPModules && module >= 0;
}
HAL_Bool HAL_CheckPDPChannel(int32_t channel) {
- return channel < kNumPDPChannels && channel >= 0;
+ return channel < kNumCTREPDPChannels && channel >= 0;
}
double HAL_GetPDPTemperature(HAL_PDPHandle handle, int32_t* status) {
+ auto pdp = pdpHandles->Get(handle);
+ if (pdp == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return 0;
+ }
+
PdpStatus3 pdpStatus;
int32_t length = 0;
uint64_t receivedTimestamp = 0;
- HAL_ReadCANPacketTimeout(handle, Status3, pdpStatus.data, &length,
+ HAL_ReadCANPacketTimeout(pdp->canHandle, Status3, pdpStatus.data, &length,
&receivedTimestamp, TimeoutMs, status);
if (*status != 0) {
@@ -179,11 +200,17 @@
}
double HAL_GetPDPVoltage(HAL_PDPHandle handle, int32_t* status) {
+ auto pdp = pdpHandles->Get(handle);
+ if (pdp == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return 0;
+ }
+
PdpStatus3 pdpStatus;
int32_t length = 0;
uint64_t receivedTimestamp = 0;
- HAL_ReadCANPacketTimeout(handle, Status3, pdpStatus.data, &length,
+ HAL_ReadCANPacketTimeout(pdp->canHandle, Status3, pdpStatus.data, &length,
&receivedTimestamp, TimeoutMs, status);
if (*status != 0) {
@@ -197,6 +224,13 @@
int32_t* status) {
if (!HAL_CheckPDPChannel(channel)) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status, fmt::format("Invalid pdp channel {}", channel));
+ return 0;
+ }
+
+ auto pdp = pdpHandles->Get(handle);
+ if (pdp == nullptr) {
+ *status = HAL_HANDLE_ERROR;
return 0;
}
@@ -207,7 +241,7 @@
if (channel <= 5) {
PdpStatus1 pdpStatus;
- HAL_ReadCANPacketTimeout(handle, Status1, pdpStatus.data, &length,
+ HAL_ReadCANPacketTimeout(pdp->canHandle, Status1, pdpStatus.data, &length,
&receivedTimestamp, TimeoutMs, status);
if (*status != 0) {
return 0;
@@ -240,7 +274,7 @@
}
} else if (channel <= 11) {
PdpStatus2 pdpStatus;
- HAL_ReadCANPacketTimeout(handle, Status2, pdpStatus.data, &length,
+ HAL_ReadCANPacketTimeout(pdp->canHandle, Status2, pdpStatus.data, &length,
&receivedTimestamp, TimeoutMs, status);
if (*status != 0) {
return 0;
@@ -273,7 +307,7 @@
}
} else {
PdpStatus3 pdpStatus;
- HAL_ReadCANPacketTimeout(handle, Status3, pdpStatus.data, &length,
+ HAL_ReadCANPacketTimeout(pdp->canHandle, Status3, pdpStatus.data, &length,
&receivedTimestamp, TimeoutMs, status);
if (*status != 0) {
return 0;
@@ -304,20 +338,32 @@
void HAL_GetPDPAllChannelCurrents(HAL_PDPHandle handle, double* currents,
int32_t* status) {
+ auto pdp = pdpHandles->Get(handle);
+ if (pdp == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
int32_t length = 0;
uint64_t receivedTimestamp = 0;
PdpStatus1 pdpStatus;
- HAL_ReadCANPacketTimeout(handle, Status1, pdpStatus.data, &length,
+ HAL_ReadCANPacketTimeout(pdp->canHandle, Status1, pdpStatus.data, &length,
&receivedTimestamp, TimeoutMs, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
PdpStatus2 pdpStatus2;
- HAL_ReadCANPacketTimeout(handle, Status2, pdpStatus2.data, &length,
+ HAL_ReadCANPacketTimeout(pdp->canHandle, Status2, pdpStatus2.data, &length,
&receivedTimestamp, TimeoutMs, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
PdpStatus3 pdpStatus3;
- HAL_ReadCANPacketTimeout(handle, Status3, pdpStatus3.data, &length,
+ HAL_ReadCANPacketTimeout(pdp->canHandle, Status3, pdpStatus3.data, &length,
&receivedTimestamp, TimeoutMs, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
currents[0] = ((static_cast<uint32_t>(pdpStatus.bits.chan1_h8) << 2) |
pdpStatus.bits.chan1_l2) *
@@ -372,12 +418,18 @@
}
double HAL_GetPDPTotalCurrent(HAL_PDPHandle handle, int32_t* status) {
+ auto pdp = pdpHandles->Get(handle);
+ if (pdp == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return 0;
+ }
+
PdpStatusEnergy pdpStatus;
int32_t length = 0;
uint64_t receivedTimestamp = 0;
- HAL_ReadCANPacketTimeout(handle, StatusEnergy, pdpStatus.data, &length,
- &receivedTimestamp, TimeoutMs, status);
+ HAL_ReadCANPacketTimeout(pdp->canHandle, StatusEnergy, pdpStatus.data,
+ &length, &receivedTimestamp, TimeoutMs, status);
if (*status != 0) {
return 0;
}
@@ -390,12 +442,18 @@
}
double HAL_GetPDPTotalPower(HAL_PDPHandle handle, int32_t* status) {
+ auto pdp = pdpHandles->Get(handle);
+ if (pdp == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return 0;
+ }
+
PdpStatusEnergy pdpStatus;
int32_t length = 0;
uint64_t receivedTimestamp = 0;
- HAL_ReadCANPacketTimeout(handle, StatusEnergy, pdpStatus.data, &length,
- &receivedTimestamp, TimeoutMs, status);
+ HAL_ReadCANPacketTimeout(pdp->canHandle, StatusEnergy, pdpStatus.data,
+ &length, &receivedTimestamp, TimeoutMs, status);
if (*status != 0) {
return 0;
}
@@ -410,12 +468,18 @@
}
double HAL_GetPDPTotalEnergy(HAL_PDPHandle handle, int32_t* status) {
+ auto pdp = pdpHandles->Get(handle);
+ if (pdp == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return 0;
+ }
+
PdpStatusEnergy pdpStatus;
int32_t length = 0;
uint64_t receivedTimestamp = 0;
- HAL_ReadCANPacketTimeout(handle, StatusEnergy, pdpStatus.data, &length,
- &receivedTimestamp, TimeoutMs, status);
+ HAL_ReadCANPacketTimeout(pdp->canHandle, StatusEnergy, pdpStatus.data,
+ &length, &receivedTimestamp, TimeoutMs, status);
if (*status != 0) {
return 0;
}
@@ -438,13 +502,25 @@
}
void HAL_ResetPDPTotalEnergy(HAL_PDPHandle handle, int32_t* status) {
+ auto pdp = pdpHandles->Get(handle);
+ if (pdp == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
uint8_t pdpControl[] = {0x40}; /* only bit set is ResetEnergy */
- HAL_WriteCANPacket(handle, pdpControl, 1, Control1, status);
+ HAL_WriteCANPacket(pdp->canHandle, pdpControl, 1, Control1, status);
}
void HAL_ClearPDPStickyFaults(HAL_PDPHandle handle, int32_t* status) {
+ auto pdp = pdpHandles->Get(handle);
+ if (pdp == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
uint8_t pdpControl[] = {0x80}; /* only bit set is ClearStickyFaults */
- HAL_WriteCANPacket(handle, pdpControl, 1, Control1, status);
+ HAL_WriteCANPacket(pdp->canHandle, pdpControl, 1, Control1, status);
}
} // extern "C"
diff --git a/hal/src/main/native/athena/CTREPDP.h b/hal/src/main/native/athena/CTREPDP.h
new file mode 100644
index 0000000..dd4b298
--- /dev/null
+++ b/hal/src/main/native/athena/CTREPDP.h
@@ -0,0 +1,136 @@
+// 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>
+
+#include "hal/Types.h"
+
+/**
+ * @defgroup hal_pdp PDP Functions
+ * @ingroup hal_capi
+ * Functions to control the Power Distribution Panel.
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initializes a Power Distribution Panel.
+ *
+ * @param module the module number to initialize
+ * @return the created PDP
+ */
+HAL_PDPHandle HAL_InitializePDP(int32_t module, const char* allocationLocation,
+ int32_t* status);
+
+/**
+ * Cleans a PDP module.
+ *
+ * @param handle the module handle
+ */
+void HAL_CleanPDP(HAL_PDPHandle handle);
+
+/**
+ * Gets the module number for a pdp.
+ */
+int32_t HAL_GetPDPModuleNumber(HAL_PDPHandle handle, int32_t* status);
+
+/**
+ * Checks if a PDP channel is valid.
+ *
+ * @param channel the channel to check
+ * @return true if the channel is valid, otherwise false
+ */
+HAL_Bool HAL_CheckPDPChannel(int32_t channel);
+
+/**
+ * Checks if a PDP module is valid.
+ *
+ * @param channel the module to check
+ * @return true if the module is valid, otherwise false
+ */
+HAL_Bool HAL_CheckPDPModule(int32_t module);
+
+/**
+ * Gets the temperature of the PDP.
+ *
+ * @param handle the module handle
+ * @return the module temperature (celsius)
+ */
+double HAL_GetPDPTemperature(HAL_PDPHandle handle, int32_t* status);
+
+/**
+ * Gets the PDP input voltage.
+ *
+ * @param handle the module handle
+ * @return the input voltage (volts)
+ */
+double HAL_GetPDPVoltage(HAL_PDPHandle handle, int32_t* status);
+
+/**
+ * Gets the current of a specific PDP channel.
+ *
+ * @param module the module
+ * @param channel the channel
+ * @return the channel current (amps)
+ */
+double HAL_GetPDPChannelCurrent(HAL_PDPHandle handle, int32_t channel,
+ int32_t* status);
+
+/**
+ * Gets the current of all 16 channels on the PDP.
+ *
+ * The array must be large enough to hold all channels.
+ *
+ * @param handle the module handle
+ * @param current the currents (output)
+ */
+void HAL_GetPDPAllChannelCurrents(HAL_PDPHandle handle, double* currents,
+ int32_t* status);
+
+/**
+ * Gets the total current of the PDP.
+ *
+ * @param handle the module handle
+ * @return the total current (amps)
+ */
+double HAL_GetPDPTotalCurrent(HAL_PDPHandle handle, int32_t* status);
+
+/**
+ * Gets the total power of the PDP.
+ *
+ * @param handle the module handle
+ * @return the total power (watts)
+ */
+double HAL_GetPDPTotalPower(HAL_PDPHandle handle, int32_t* status);
+
+/**
+ * Gets the total energy of the PDP.
+ *
+ * @param handle the module handle
+ * @return the total energy (joules)
+ */
+double HAL_GetPDPTotalEnergy(HAL_PDPHandle handle, int32_t* status);
+
+/**
+ * Resets the PDP accumulated energy.
+ *
+ * @param handle the module handle
+ */
+void HAL_ResetPDPTotalEnergy(HAL_PDPHandle handle, int32_t* status);
+
+/**
+ * Clears any PDP sticky faults.
+ *
+ * @param handle the module handle
+ */
+void HAL_ClearPDPStickyFaults(HAL_PDPHandle handle, int32_t* status);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+/** @} */
diff --git a/hal/src/main/native/athena/Compressor.cpp b/hal/src/main/native/athena/Compressor.cpp
deleted file mode 100644
index f381305..0000000
--- a/hal/src/main/native/athena/Compressor.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
-
-#include "hal/Compressor.h"
-
-#include "HALInitializer.h"
-#include "PCMInternal.h"
-#include "PortsInternal.h"
-#include "ctre/PCM.h"
-#include "hal/Errors.h"
-#include "hal/handles/HandlesInternal.h"
-
-using namespace hal;
-
-namespace hal {
-namespace init {
-void InitializeCompressor() {}
-} // namespace init
-} // namespace hal
-
-extern "C" {
-
-HAL_CompressorHandle HAL_InitializeCompressor(int32_t module, int32_t* status) {
- hal::init::CheckInit();
- // Use status to check for invalid index
- initializePCM(module, status);
- if (*status != 0) {
- return HAL_kInvalidHandle;
- }
-
- // As compressors can have unlimited objects, just create a
- // handle with the module number as the index.
-
- return (HAL_CompressorHandle)createHandle(static_cast<int16_t>(module),
- HAL_HandleEnum::Compressor, 0);
-}
-
-HAL_Bool HAL_CheckCompressorModule(int32_t module) {
- return module < kNumPCMModules && module >= 0;
-}
-
-HAL_Bool HAL_GetCompressor(HAL_CompressorHandle compressorHandle,
- int32_t* status) {
- int16_t index =
- getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0);
- if (index == InvalidHandleIndex) {
- *status = HAL_HANDLE_ERROR;
- return false;
- }
- bool value;
-
- *status = PCM_modules[index]->GetCompressor(value);
-
- return value;
-}
-
-void HAL_SetCompressorClosedLoopControl(HAL_CompressorHandle compressorHandle,
- HAL_Bool value, int32_t* status) {
- int16_t index =
- getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0);
- if (index == InvalidHandleIndex) {
- *status = HAL_HANDLE_ERROR;
- return;
- }
-
- *status = PCM_modules[index]->SetClosedLoopControl(value);
-}
-
-HAL_Bool HAL_GetCompressorClosedLoopControl(
- HAL_CompressorHandle compressorHandle, int32_t* status) {
- int16_t index =
- getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0);
- if (index == InvalidHandleIndex) {
- *status = HAL_HANDLE_ERROR;
- return false;
- }
- bool value;
-
- *status = PCM_modules[index]->GetClosedLoopControl(value);
-
- return value;
-}
-
-HAL_Bool HAL_GetCompressorPressureSwitch(HAL_CompressorHandle compressorHandle,
- int32_t* status) {
- int16_t index =
- getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0);
- if (index == InvalidHandleIndex) {
- *status = HAL_HANDLE_ERROR;
- return false;
- }
- bool value;
-
- *status = PCM_modules[index]->GetPressure(value);
-
- return value;
-}
-
-double HAL_GetCompressorCurrent(HAL_CompressorHandle compressorHandle,
- int32_t* status) {
- int16_t index =
- getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0);
- if (index == InvalidHandleIndex) {
- *status = HAL_HANDLE_ERROR;
- return 0;
- }
- float value;
-
- *status = PCM_modules[index]->GetCompressorCurrent(value);
-
- return value;
-}
-HAL_Bool HAL_GetCompressorCurrentTooHighFault(
- HAL_CompressorHandle compressorHandle, int32_t* status) {
- int16_t index =
- getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0);
- if (index == InvalidHandleIndex) {
- *status = HAL_HANDLE_ERROR;
- return false;
- }
- bool value;
-
- *status = PCM_modules[index]->GetCompressorCurrentTooHighFault(value);
-
- return value;
-}
-HAL_Bool HAL_GetCompressorCurrentTooHighStickyFault(
- HAL_CompressorHandle compressorHandle, int32_t* status) {
- int16_t index =
- getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0);
- if (index == InvalidHandleIndex) {
- *status = HAL_HANDLE_ERROR;
- return false;
- }
- bool value;
-
- *status = PCM_modules[index]->GetCompressorCurrentTooHighStickyFault(value);
-
- return value;
-}
-HAL_Bool HAL_GetCompressorShortedStickyFault(
- HAL_CompressorHandle compressorHandle, int32_t* status) {
- int16_t index =
- getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0);
- if (index == InvalidHandleIndex) {
- *status = HAL_HANDLE_ERROR;
- return false;
- }
- bool value;
-
- *status = PCM_modules[index]->GetCompressorShortedStickyFault(value);
-
- return value;
-}
-HAL_Bool HAL_GetCompressorShortedFault(HAL_CompressorHandle compressorHandle,
- int32_t* status) {
- int16_t index =
- getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0);
- if (index == InvalidHandleIndex) {
- *status = HAL_HANDLE_ERROR;
- return false;
- }
- bool value;
-
- *status = PCM_modules[index]->GetCompressorShortedFault(value);
-
- return value;
-}
-HAL_Bool HAL_GetCompressorNotConnectedStickyFault(
- HAL_CompressorHandle compressorHandle, int32_t* status) {
- int16_t index =
- getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0);
- if (index == InvalidHandleIndex) {
- *status = HAL_HANDLE_ERROR;
- return false;
- }
- bool value;
-
- *status = PCM_modules[index]->GetCompressorNotConnectedStickyFault(value);
-
- return value;
-}
-HAL_Bool HAL_GetCompressorNotConnectedFault(
- HAL_CompressorHandle compressorHandle, int32_t* status) {
- int16_t index =
- getHandleTypedIndex(compressorHandle, HAL_HandleEnum::Compressor, 0);
- if (index == InvalidHandleIndex) {
- *status = HAL_HANDLE_ERROR;
- return false;
- }
- bool value;
-
- *status = PCM_modules[index]->GetCompressorNotConnectedFault(value);
-
- return value;
-}
-
-} // extern "C"
diff --git a/hal/src/main/native/athena/Constants.cpp b/hal/src/main/native/athena/Constants.cpp
index 6af443d..a312935 100644
--- a/hal/src/main/native/athena/Constants.cpp
+++ b/hal/src/main/native/athena/Constants.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/Constants.h"
@@ -11,11 +8,9 @@
using namespace hal;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeConstants() {}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
diff --git a/hal/src/main/native/athena/ConstantsInternal.h b/hal/src/main/native/athena/ConstantsInternal.h
index 55bbdee..21fece4 100644
--- a/hal/src/main/native/athena/ConstantsInternal.h
+++ b/hal/src/main/native/athena/ConstantsInternal.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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
diff --git a/hal/src/main/native/athena/Counter.cpp b/hal/src/main/native/athena/Counter.cpp
index 6d7e254..7f84df8 100644
--- a/hal/src/main/native/athena/Counter.cpp
+++ b/hal/src/main/native/athena/Counter.cpp
@@ -1,15 +1,15 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/Counter.h"
+#include <fmt/format.h>
+
#include "ConstantsInternal.h"
#include "DigitalInternal.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/HAL.h"
#include "hal/handles/LimitedHandleResource.h"
@@ -28,16 +28,14 @@
static LimitedHandleResource<HAL_CounterHandle, Counter, kNumCounters,
HAL_HandleEnum::Counter>* counterHandles;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeCounter() {
static LimitedHandleResource<HAL_CounterHandle, Counter, kNumCounters,
HAL_HandleEnum::Counter>
ch;
counterHandles = &ch;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
@@ -151,6 +149,9 @@
// TODO: wpi_setWPIErrorWithContext(ParameterOutOfRange, "Counter only
// supports DownSource in TwoPulse and ExternalDirection modes.");
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status,
+ "Counter only supports DownSource in TwoPulse and "
+ "ExternalDirection mode.");
return;
}
@@ -265,6 +266,10 @@
}
if (samplesToAverage < 1 || samplesToAverage > 127) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status, fmt::format("Samples to average must be between "
+ "1 and 127 inclusive. Requested {}",
+ samplesToAverage));
+ return;
}
counter->counter->writeTimerConfig_AverageSize(samplesToAverage, status);
}
@@ -362,10 +367,11 @@
}
if (counter->counter->readConfig_Mode(status) ==
HAL_Counter_kExternalDirection) {
- if (reverseDirection)
+ if (reverseDirection) {
HAL_SetCounterDownSourceEdge(counterHandle, true, true, status);
- else
+ } else {
HAL_SetCounterDownSourceEdge(counterHandle, false, true, status);
+ }
}
}
diff --git a/hal/src/main/native/athena/DIO.cpp b/hal/src/main/native/athena/DIO.cpp
index dc4631e..7b26dd1 100644
--- a/hal/src/main/native/athena/DIO.cpp
+++ b/hal/src/main/native/athena/DIO.cpp
@@ -1,19 +1,16 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/DIO.h"
#include <cmath>
+#include <cstdio>
#include <thread>
-#include <wpi/raw_ostream.h>
-
#include "DigitalInternal.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/cpp/fpga_clock.h"
#include "hal/handles/HandlesInternal.h"
@@ -28,8 +25,7 @@
kNumDigitalPWMOutputs, HAL_HandleEnum::DigitalPWM>*
digitalPWMHandles;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeDIO() {
static LimitedHandleResource<HAL_DigitalPWMHandle, uint8_t,
kNumDigitalPWMOutputs,
@@ -37,36 +33,45 @@
dpH;
digitalPWMHandles = &dpH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
HAL_DigitalHandle HAL_InitializeDIOPort(HAL_PortHandle portHandle,
- HAL_Bool input, int32_t* status) {
+ HAL_Bool input,
+ const char* allocationLocation,
+ int32_t* status) {
hal::init::CheckInit();
initializeDigital(status);
- if (*status != 0) return HAL_kInvalidHandle;
-
- int16_t channel = getPortHandleChannel(portHandle);
- if (channel == InvalidHandleIndex || channel >= kNumDigitalChannels) {
- *status = PARAMETER_OUT_OF_RANGE;
+ if (*status != 0) {
return HAL_kInvalidHandle;
}
- auto handle =
- digitalChannelHandles->Allocate(channel, HAL_HandleEnum::DIO, status);
-
- if (*status != 0)
- return HAL_kInvalidHandle; // failed to allocate. Pass error back.
-
- auto port = digitalChannelHandles->Get(handle, HAL_HandleEnum::DIO);
- if (port == nullptr) { // would only occur on thread issue.
- *status = HAL_HANDLE_ERROR;
+ int16_t channel = getPortHandleChannel(portHandle);
+ if (channel == InvalidHandleIndex || channel >= kNumDigitalChannels) {
+ *status = RESOURCE_OUT_OF_RANGE;
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for DIO", 0,
+ kNumDigitalChannels, channel);
return HAL_kInvalidHandle;
}
+ HAL_DigitalHandle handle;
+
+ auto port = digitalChannelHandles->Allocate(channel, HAL_HandleEnum::DIO,
+ &handle, status);
+
+ if (*status != 0) {
+ if (port) {
+ hal::SetLastErrorPreviouslyAllocated(status, "PWM or DIO", channel,
+ port->previousAllocation);
+ } else {
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for DIO", 0,
+ kNumDigitalChannels, channel);
+ }
+ return HAL_kInvalidHandle; // failed to allocate. Pass error back.
+ }
+
port->channel = static_cast<uint8_t>(channel);
std::scoped_lock lock(digitalDIOMutex);
@@ -116,6 +121,7 @@
}
digitalSystem->writeOutputEnable(outputEnable, status);
+ port->previousAllocation = allocationLocation ? allocationLocation : "";
return handle;
}
@@ -127,7 +133,8 @@
void HAL_FreeDIOPort(HAL_DigitalHandle dioPortHandle) {
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
// no status, so no need to check for a proper free.
- if (port == nullptr) return;
+ if (port == nullptr)
+ return;
digitalChannelHandles->Free(dioPortHandle, HAL_HandleEnum::DIO);
// Wait for no other object to hold this handle.
@@ -135,8 +142,8 @@
while (port.use_count() != 1) {
auto current = hal::fpga_clock::now();
if (start + std::chrono::seconds(1) < current) {
- wpi::outs() << "DIO handle free timeout\n";
- wpi::outs().flush();
+ std::puts("DIO handle free timeout");
+ std::fflush(stdout);
break;
}
std::this_thread::yield();
@@ -189,9 +196,11 @@
// higher freq.
// TODO: Round in the linear rate domain.
initializeDigital(status);
- if (*status != 0) return;
- uint16_t pwmPeriodPower = static_cast<uint16_t>(
- std::log(1.0 / (16 * 1.0E-6 * rate)) / std::log(2.0) + 0.5);
+ if (*status != 0) {
+ return;
+ }
+ uint16_t pwmPeriodPower =
+ std::lround(std::log(1.0 / (16 * 1.0E-6 * rate)) / std::log(2.0));
digitalSystem->writePWMPeriodPower(pwmPeriodPower, status);
}
@@ -203,10 +212,16 @@
return;
}
int32_t id = *port;
- if (dutyCycle > 1.0) dutyCycle = 1.0;
- if (dutyCycle < 0.0) dutyCycle = 0.0;
+ if (dutyCycle > 1.0) {
+ dutyCycle = 1.0;
+ }
+ if (dutyCycle < 0.0) {
+ dutyCycle = 0.0;
+ }
double rawDutyCycle = 256.0 * dutyCycle;
- if (rawDutyCycle > 255.5) rawDutyCycle = 255.5;
+ if (rawDutyCycle > 255.5) {
+ rawDutyCycle = 255.5;
+ }
{
std::scoped_lock lock(digitalPwmMutex);
uint16_t pwmPeriodPower = digitalSystem->readPWMPeriodPower(status);
@@ -251,10 +266,35 @@
return;
}
if (value != 0 && value != 1) {
- if (value != 0) value = 1;
+ if (value != 0) {
+ value = 1;
+ }
}
{
std::scoped_lock lock(digitalDIOMutex);
+
+ tDIO::tOutputEnable currentOutputEnable =
+ digitalSystem->readOutputEnable(status);
+
+ HAL_Bool isInput = false;
+
+ if (port->channel >= kNumDigitalHeaders + kNumDigitalMXPChannels) {
+ isInput =
+ ((currentOutputEnable.SPIPort >> remapSPIChannel(port->channel)) &
+ 1) == 0;
+ } else if (port->channel < kNumDigitalHeaders) {
+ isInput = ((currentOutputEnable.Headers >> port->channel) & 1) == 0;
+ } else {
+ isInput = ((currentOutputEnable.MXP >> remapMXPChannel(port->channel)) &
+ 1) == 0;
+ }
+
+ if (isInput) {
+ *status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status, "Cannot set output of an input channel");
+ return;
+ }
+
tDIO::tDO currentDIO = digitalSystem->readDO(status);
if (port->channel >= kNumDigitalHeaders + kNumDigitalMXPChannels) {
@@ -358,11 +398,11 @@
if (port->channel >= kNumDigitalHeaders + kNumDigitalMXPChannels) {
return ((currentOutputEnable.SPIPort >> remapSPIChannel(port->channel)) &
- 1) != 0;
+ 1) == 0;
} else if (port->channel < kNumDigitalHeaders) {
- return ((currentOutputEnable.Headers >> port->channel) & 1) != 0;
+ return ((currentOutputEnable.Headers >> port->channel) & 1) == 0;
} else {
- return ((currentOutputEnable.MXP >> remapMXPChannel(port->channel)) & 1) !=
+ return ((currentOutputEnable.MXP >> remapMXPChannel(port->channel)) & 1) ==
0;
}
}
@@ -410,7 +450,9 @@
HAL_Bool HAL_IsAnyPulsing(int32_t* status) {
initializeDigital(status);
- if (*status != 0) return false;
+ if (*status != 0) {
+ return false;
+ }
tDIO::tPulse pulseRegister = digitalSystem->readPulse(status);
return pulseRegister.Headers != 0 && pulseRegister.MXP != 0 &&
pulseRegister.SPIPort != 0;
@@ -459,7 +501,9 @@
void HAL_SetFilterPeriod(int32_t filterIndex, int64_t value, int32_t* status) {
initializeDigital(status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
std::scoped_lock lock(digitalDIOMutex);
digitalSystem->writeFilterPeriodHdr(filterIndex, value, status);
if (*status == 0) {
@@ -469,7 +513,9 @@
int64_t HAL_GetFilterPeriod(int32_t filterIndex, int32_t* status) {
initializeDigital(status);
- if (*status != 0) return 0;
+ if (*status != 0) {
+ return 0;
+ }
uint32_t hdrPeriod = 0;
uint32_t mxpPeriod = 0;
{
diff --git a/hal/src/main/native/athena/DMA.cpp b/hal/src/main/native/athena/DMA.cpp
index ee39d2d..f7d8b08 100644
--- a/hal/src/main/native/athena/DMA.cpp
+++ b/hal/src/main/native/athena/DMA.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/DMA.h"
@@ -14,8 +11,10 @@
#include <type_traits>
#include "AnalogInternal.h"
+#include "ConstantsInternal.h"
#include "DigitalInternal.h"
#include "EncoderInternal.h"
+#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/AnalogAccumulator.h"
#include "hal/AnalogGyro.h"
@@ -73,15 +72,13 @@
static hal::LimitedHandleResource<HAL_DMAHandle, DMA, 1, HAL_HandleEnum::DMA>*
dmaHandles;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeDMA() {
static hal::LimitedHandleResource<HAL_DMAHandle, DMA, 1, HAL_HandleEnum::DMA>
dH;
dmaHandles = &dH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
@@ -107,19 +104,25 @@
return HAL_kInvalidHandle;
}
- dma->aDMA->writeConfig_ExternalClock(false, status);
- if (*status != 0) {
- dmaHandles->Free(handle);
- return HAL_kInvalidHandle;
+ std::memset(&dma->captureStore, 0, sizeof(dma->captureStore));
+
+ tDMA::tConfig config;
+ std::memset(&config, 0, sizeof(config));
+ config.Pause = true;
+ dma->aDMA->writeConfig(config, status);
+
+ dma->aDMA->writeRate(1, status);
+
+ tDMA::tExternalTriggers newTrigger;
+ std::memset(&newTrigger, 0, sizeof(newTrigger));
+ for (unsigned char reg = 0; reg < tDMA::kNumExternalTriggersRegisters;
+ reg++) {
+ for (unsigned char bit = 0; bit < tDMA::kNumExternalTriggersElements;
+ bit++) {
+ dma->aDMA->writeExternalTriggers(reg, bit, newTrigger, status);
+ }
}
- HAL_SetDMARate(handle, 1, status);
- if (*status != 0) {
- dmaHandles->Free(handle);
- return HAL_kInvalidHandle;
- }
-
- HAL_SetDMAPause(handle, false, status);
return handle;
}
@@ -127,7 +130,8 @@
auto dma = dmaHandles->Get(handle);
dmaHandles->Free(handle);
- if (!dma) return;
+ if (!dma)
+ return;
int32_t status = 0;
if (dma->manager) {
@@ -142,20 +146,44 @@
return;
}
+ if (!dma->manager) {
+ *status = HAL_INVALID_DMA_STATE;
+ return;
+ }
+
dma->aDMA->writeConfig_Pause(pause, status);
}
-void HAL_SetDMARate(HAL_DMAHandle handle, int32_t cycles, int32_t* status) {
+
+void HAL_SetDMATimedTrigger(HAL_DMAHandle handle, double seconds,
+ int32_t* status) {
+ constexpr double baseMultipler = kSystemClockTicksPerMicrosecond * 1000000;
+ uint32_t cycles = static_cast<uint32_t>(baseMultipler * seconds);
+ HAL_SetDMATimedTriggerCycles(handle, cycles, status);
+}
+
+void HAL_SetDMATimedTriggerCycles(HAL_DMAHandle handle, uint32_t cycles,
+ int32_t* status) {
auto dma = dmaHandles->Get(handle);
if (!dma) {
*status = HAL_HANDLE_ERROR;
return;
}
+ if (dma->manager) {
+ *status = HAL_INVALID_DMA_ADDITION;
+ return;
+ }
+
if (cycles < 1) {
cycles = 1;
}
- dma->aDMA->writeRate(static_cast<uint32_t>(cycles), status);
+ dma->aDMA->writeConfig_ExternalClock(false, status);
+ if (*status != 0) {
+ return;
+ }
+
+ dma->aDMA->writeRate(cycles, status);
}
void HAL_AddDMAEncoder(HAL_DMAHandle handle, HAL_EncoderHandle encoderHandle,
@@ -480,20 +508,20 @@
}
}
-void HAL_SetDMAExternalTrigger(HAL_DMAHandle handle,
- HAL_Handle digitalSourceHandle,
- HAL_AnalogTriggerType analogTriggerType,
- HAL_Bool rising, HAL_Bool falling,
- int32_t* status) {
+int32_t HAL_SetDMAExternalTrigger(HAL_DMAHandle handle,
+ HAL_Handle digitalSourceHandle,
+ HAL_AnalogTriggerType analogTriggerType,
+ HAL_Bool rising, HAL_Bool falling,
+ int32_t* status) {
auto dma = dmaHandles->Get(handle);
if (!dma) {
*status = HAL_HANDLE_ERROR;
- return;
+ return 0;
}
if (dma->manager) {
*status = HAL_INVALID_DMA_ADDITION;
- return;
+ return 0;
}
int index = 0;
@@ -507,19 +535,21 @@
if (index == 8) {
*status = NO_AVAILABLE_RESOURCES;
- return;
+ return 0;
}
dma->captureStore.triggerChannels |= (1 << index);
auto channelIndex = index;
- auto isExternalClock = dma->aDMA->readConfig_ExternalClock(status);
- if (*status == 0 && !isExternalClock) {
- dma->aDMA->writeConfig_ExternalClock(true, status);
- if (*status != 0) return;
- } else if (*status != 0) {
- return;
+ dma->aDMA->writeConfig_ExternalClock(true, status);
+ if (*status != 0) {
+ return 0;
+ }
+
+ dma->aDMA->writeRate(1, status);
+ if (*status != 0) {
+ return 0;
}
uint8_t pin = 0;
@@ -530,7 +560,10 @@
if (!success) {
*status = PARAMETER_OUT_OF_RANGE;
- return;
+ hal::SetLastError(status,
+ "Digital Source unabled to be mapped properly. Likely "
+ "invalid handle passed.");
+ return 0;
}
tDMA::tExternalTriggers newTrigger;
@@ -542,6 +575,55 @@
dma->aDMA->writeExternalTriggers(channelIndex / 4, channelIndex % 4,
newTrigger, status);
+ return index;
+}
+
+void HAL_ClearDMASensors(HAL_DMAHandle handle, int32_t* status) {
+ auto dma = dmaHandles->Get(handle);
+ if (!dma) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
+ if (dma->manager) {
+ *status = HAL_INVALID_DMA_STATE;
+ return;
+ }
+
+ bool existingExternal = dma->aDMA->readConfig_ExternalClock(status);
+ if (*status != 0) {
+ return;
+ }
+
+ tDMA::tConfig config;
+ std::memset(&config, 0, sizeof(config));
+ config.Pause = true;
+ config.ExternalClock = existingExternal;
+ dma->aDMA->writeConfig(config, status);
+}
+
+void HAL_ClearDMAExternalTriggers(HAL_DMAHandle handle, int32_t* status) {
+ auto dma = dmaHandles->Get(handle);
+ if (!dma) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
+ if (dma->manager) {
+ *status = HAL_INVALID_DMA_STATE;
+ return;
+ }
+
+ dma->captureStore.triggerChannels = 0;
+ tDMA::tExternalTriggers newTrigger;
+ std::memset(&newTrigger, 0, sizeof(newTrigger));
+ for (unsigned char reg = 0; reg < tDMA::kNumExternalTriggersRegisters;
+ reg++) {
+ for (unsigned char bit = 0; bit < tDMA::kNumExternalTriggersElements;
+ bit++) {
+ dma->aDMA->writeExternalTriggers(reg, bit, newTrigger, status);
+ }
+ }
}
void HAL_StartDMA(HAL_DMAHandle handle, int32_t queueDepth, int32_t* status) {
@@ -552,12 +634,14 @@
}
if (dma->manager) {
- *status = INCOMPATIBLE_STATE;
+ *status = HAL_INVALID_DMA_STATE;
return;
}
tDMA::tConfig config = dma->aDMA->readConfig(status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
{
size_t accum_size = 0;
@@ -594,12 +678,15 @@
dma->captureStore.captureSize = accum_size + 1;
}
- dma->manager = std::make_unique<tDMAManager>(
- g_DMA_index, queueDepth * dma->captureStore.captureSize, status);
+ uint32_t byteDepth = queueDepth * dma->captureStore.captureSize;
+
+ dma->manager = std::make_unique<tDMAManager>(g_DMA_index, byteDepth, status);
if (*status != 0) {
return;
}
+ dma->aDMA->writeConfig_Pause(false, status);
+
dma->manager->start(status);
dma->manager->stop(status);
dma->manager->start(status);
@@ -613,6 +700,8 @@
}
if (dma->manager) {
+ dma->aDMA->writeConfig_Pause(true, status);
+ *status = 0;
dma->manager->stop(status);
dma->manager = nullptr;
}
@@ -625,7 +714,7 @@
enum HAL_DMAReadStatus HAL_ReadDMADirect(void* dmaPointer,
HAL_DMASample* dmaSample,
- int32_t timeoutMs,
+ double timeoutSeconds,
int32_t* remainingOut,
int32_t* status) {
DMA* dma = static_cast<DMA*>(dmaPointer);
@@ -633,12 +722,13 @@
size_t remainingBytes = 0;
if (!dma->manager) {
- *status = INCOMPATIBLE_STATE;
+ *status = HAL_INVALID_DMA_STATE;
return HAL_DMA_ERROR;
}
dma->manager->read(dmaSample->readBuffer, dma->captureStore.captureSize,
- timeoutMs, &remainingBytes, status);
+ static_cast<uint32_t>(timeoutSeconds * 1000),
+ &remainingBytes, status);
*remainingOut = remainingBytes / dma->captureStore.captureSize;
@@ -663,15 +753,16 @@
}
enum HAL_DMAReadStatus HAL_ReadDMA(HAL_DMAHandle handle,
- HAL_DMASample* dmaSample, int32_t timeoutMs,
- int32_t* remainingOut, int32_t* status) {
+ HAL_DMASample* dmaSample,
+ double timeoutSeconds, int32_t* remainingOut,
+ int32_t* status) {
auto dma = dmaHandles->Get(handle);
if (!dma) {
*status = HAL_HANDLE_ERROR;
return HAL_DMA_ERROR;
}
- return HAL_ReadDMADirect(dma.get(), dmaSample, timeoutMs, remainingOut,
+ return HAL_ReadDMADirect(dma.get(), dmaSample, timeoutSeconds, remainingOut,
status);
}
diff --git a/hal/src/main/native/athena/DigitalInternal.cpp b/hal/src/main/native/athena/DigitalInternal.cpp
index 205ce3e..63ea0aa 100644
--- a/hal/src/main/native/athena/DigitalInternal.cpp
+++ b/hal/src/main/native/athena/DigitalInternal.cpp
@@ -1,13 +1,11 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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 "DigitalInternal.h"
#include <atomic>
+#include <cmath>
#include <thread>
#include <FRC_NetworkCommunication/LoadOut.h>
@@ -46,8 +44,12 @@
} // namespace init
namespace detail {
-wpi::mutex& UnsafeGetDIOMutex() { return digitalDIOMutex; }
-tDIO* UnsafeGetDigialSystem() { return digitalSystem.get(); }
+wpi::mutex& UnsafeGetDIOMutex() {
+ return digitalDIOMutex;
+}
+tDIO* UnsafeGetDigialSystem() {
+ return digitalSystem.get();
+}
int32_t ComputeDigitalMask(HAL_DigitalHandle handle, int32_t* status) {
auto port = digitalChannelHandles->Get(handle, HAL_HandleEnum::DIO);
if (port == nullptr) {
@@ -72,11 +74,15 @@
static std::atomic_bool initialized{false};
static wpi::mutex initializeMutex;
// Initial check, as if it's true initialization has finished
- if (initialized) return;
+ if (initialized) {
+ return;
+ }
std::scoped_lock lock(initializeMutex);
// Second check in case another thread was waiting
- if (initialized) return;
+ if (initialized) {
+ return;
+ }
digitalSystem.reset(tDIO::create(status));
@@ -92,7 +98,8 @@
// Make sure that the 9403 IONode has had a chance to initialize before
// continuing.
- while (pwmSystem->readLoopTiming(status) == 0) std::this_thread::yield();
+ while (pwmSystem->readLoopTiming(status) == 0)
+ std::this_thread::yield();
if (pwmSystem->readLoopTiming(status) != kExpectedLoopTiming) {
*status = LOOP_TIMING_ERROR; // NOTE: Doesn't display the error
@@ -102,10 +109,10 @@
double loopTime = pwmSystem->readLoopTiming(status) /
(kSystemClockTicksPerMicrosecond * 1e3);
- pwmSystem->writeConfig_Period(
- static_cast<uint16_t>(kDefaultPwmPeriod / loopTime + 0.5), status);
- uint16_t minHigh = static_cast<uint16_t>(
- (kDefaultPwmCenter - kDefaultPwmStepsDown * loopTime) / loopTime + 0.5);
+ pwmSystem->writeConfig_Period(std::lround(kDefaultPwmPeriod / loopTime),
+ status);
+ uint16_t minHigh = std::lround(
+ (kDefaultPwmCenter - kDefaultPwmStepsDown * loopTime) / loopTime);
pwmSystem->writeConfig_MinHigh(minHigh, status);
// Ensure that PWM output values are set to OFF
for (uint8_t pwmIndex = 0; pwmIndex < kNumPWMChannels; pwmIndex++) {
@@ -158,12 +165,22 @@
}
analogTrigger = false;
return true;
- } else {
- return false;
+ } else if (isHandleType(digitalSourceHandle, HAL_HandleEnum::PWM)) {
+ // PWM's on MXP port are supported as a digital source
+ int32_t index = getHandleIndex(digitalSourceHandle);
+ if (index >= kNumPWMHeaders) {
+ channel = remapMXPPWMChannel(index);
+ module = 1;
+ analogTrigger = false;
+ return true;
+ }
}
+ return false;
}
-int32_t remapMXPChannel(int32_t channel) { return channel - 10; }
+int32_t remapMXPChannel(int32_t channel) {
+ return channel - 10;
+}
int32_t remapMXPPWMChannel(int32_t channel) {
if (channel < 14) {
@@ -173,7 +190,9 @@
}
}
-int32_t remapSPIChannel(int32_t channel) { return channel - 26; }
+int32_t remapSPIChannel(int32_t channel) {
+ return channel - 26;
+}
} // namespace hal
diff --git a/hal/src/main/native/athena/DigitalInternal.h b/hal/src/main/native/athena/DigitalInternal.h
index 2cb9b3c..6b1e909 100644
--- a/hal/src/main/native/athena/DigitalInternal.h
+++ b/hal/src/main/native/athena/DigitalInternal.h
@@ -1,15 +1,13 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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>
#include <memory>
+#include <string>
#include <wpi/mutex.h>
@@ -73,6 +71,7 @@
int32_t centerPwm = 0;
int32_t deadbandMinPwm = 0;
int32_t minPwm = 0;
+ std::string previousAllocation;
};
extern DigitalHandleResource<HAL_DigitalHandle, DigitalPort,
@@ -101,13 +100,15 @@
*/
constexpr int32_t remapDigitalChannelToBitfieldChannel(int32_t channel) {
// First 10 are headers
- if (channel < kNumDigitalHeaders) return channel;
- // 2nd group of 16 are mxp. So if mxp port, add 6, since they start at 10
- else if (channel < kNumDigitalMXPChannels)
+ if (channel < kNumDigitalHeaders) {
+ return channel;
+ // 2nd group of 16 are mxp. So if mxp port, add 6, since they start at 10
+ } else if (channel < kNumDigitalMXPChannels) {
return channel + 6;
- // Assume SPI, so remove MXP channels
- else
+ // Assume SPI, so remove MXP channels
+ } else {
return channel - kNumDigitalMXPChannels;
+ }
}
/**
diff --git a/hal/src/main/native/athena/DutyCycle.cpp b/hal/src/main/native/athena/DutyCycle.cpp
index 3749a2b..6d70570 100644
--- a/hal/src/main/native/athena/DutyCycle.cpp
+++ b/hal/src/main/native/athena/DutyCycle.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/DutyCycle.h"
diff --git a/hal/src/main/native/athena/DutyCycleInternal.h b/hal/src/main/native/athena/DutyCycleInternal.h
index 33a8ff2..ef49e25 100644
--- a/hal/src/main/native/athena/DutyCycleInternal.h
+++ b/hal/src/main/native/athena/DutyCycleInternal.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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
diff --git a/hal/src/main/native/athena/Encoder.cpp b/hal/src/main/native/athena/Encoder.cpp
index be8c203..6edfea3 100644
--- a/hal/src/main/native/athena/Encoder.cpp
+++ b/hal/src/main/native/athena/Encoder.cpp
@@ -1,15 +1,15 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/Encoder.h"
+#include <fmt/format.h>
+
#include "EncoderInternal.h"
#include "FPGAEncoder.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/ChipObject.h"
#include "hal/Counter.h"
@@ -49,6 +49,8 @@
}
default:
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status, fmt::format("Encoding type {} invalid.",
+ static_cast<int>(encodingType)));
return;
}
}
@@ -63,15 +65,23 @@
m_encodingScale = encodingType == HAL_Encoder_k1X ? 1 : 2;
m_counter =
HAL_InitializeCounter(HAL_Counter_kExternalDirection, &m_index, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
HAL_SetCounterMaxPeriod(m_counter, 0.5, status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
HAL_SetCounterUpSource(m_counter, digitalSourceHandleA, analogTriggerTypeA,
status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
HAL_SetCounterDownSource(m_counter, digitalSourceHandleB, analogTriggerTypeB,
status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
if (encodingType == HAL_Encoder_k1X) {
HAL_SetCounterUpSourceEdge(m_counter, true, false, status);
HAL_SetCounterAverageSize(m_counter, 1, status);
@@ -176,6 +186,9 @@
void Encoder::SetSamplesToAverage(int32_t samplesToAverage, int32_t* status) {
if (samplesToAverage < 1 || samplesToAverage > 127) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status, fmt::format("Samples to average must be between "
+ "1 and 127 inclusive. Requested {}",
+ samplesToAverage));
return;
}
if (m_counter) {
@@ -226,8 +239,7 @@
kNumEncoders + kNumCounters,
HAL_HandleEnum::Encoder>* encoderHandles;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeEncoder() {
static LimitedClassedHandleResource<HAL_EncoderHandle, Encoder,
kNumEncoders + kNumCounters,
@@ -235,15 +247,16 @@
eH;
encoderHandles = &eH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
namespace hal {
bool GetEncoderBaseHandle(HAL_EncoderHandle handle,
HAL_FPGAEncoderHandle* fpgaHandle,
HAL_CounterHandle* counterHandle) {
auto encoder = encoderHandles->Get(handle);
- if (!handle) return false;
+ if (!encoder) {
+ return false;
+ }
*fpgaHandle = encoder->m_encoder;
*counterHandle = encoder->m_counter;
@@ -261,7 +274,9 @@
auto encoder = std::make_shared<Encoder>(
digitalSourceHandleA, analogTriggerTypeA, digitalSourceHandleB,
analogTriggerTypeB, reverseDirection, encodingType, status);
- if (*status != 0) return HAL_kInvalidHandle; // return in creation error
+ if (*status != 0) {
+ return HAL_kInvalidHandle; // return in creation error
+ }
auto handle = encoderHandles->Allocate(encoder);
if (handle == HAL_kInvalidHandle) {
*status = NO_AVAILABLE_RESOURCES;
diff --git a/hal/src/main/native/athena/EncoderInternal.h b/hal/src/main/native/athena/EncoderInternal.h
index bed4ee3..5591a6f 100644
--- a/hal/src/main/native/athena/EncoderInternal.h
+++ b/hal/src/main/native/athena/EncoderInternal.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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
diff --git a/hal/src/main/native/athena/FPGAEncoder.cpp b/hal/src/main/native/athena/FPGAEncoder.cpp
index 7f2e107..9965d43 100644
--- a/hal/src/main/native/athena/FPGAEncoder.cpp
+++ b/hal/src/main/native/athena/FPGAEncoder.cpp
@@ -1,16 +1,16 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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 "FPGAEncoder.h"
#include <memory>
+#include <fmt/format.h>
+
#include "DigitalInternal.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/handles/LimitedHandleResource.h"
@@ -30,16 +30,14 @@
static LimitedHandleResource<HAL_FPGAEncoderHandle, Encoder, kNumEncoders,
HAL_HandleEnum::FPGAEncoder>* fpgaEncoderHandles;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeFPGAEncoder() {
static LimitedHandleResource<HAL_FPGAEncoderHandle, Encoder, kNumEncoders,
HAL_HandleEnum::FPGAEncoder>
feH;
fpgaEncoderHandles = &feH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
@@ -198,6 +196,10 @@
}
if (samplesToAverage < 1 || samplesToAverage > 127) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status, fmt::format("Samples to average must be between "
+ "1 and 127 inclusive. Requested {}",
+ samplesToAverage));
+ return;
}
encoder->encoder->writeTimerConfig_AverageSize(samplesToAverage, status);
}
diff --git a/hal/src/main/native/athena/FPGAEncoder.h b/hal/src/main/native/athena/FPGAEncoder.h
index f29aeae..b401ccd 100644
--- a/hal/src/main/native/athena/FPGAEncoder.h
+++ b/hal/src/main/native/athena/FPGAEncoder.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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
diff --git a/hal/src/main/native/athena/FRCDriverStation.cpp b/hal/src/main/native/athena/FRCDriverStation.cpp
index 51fe327..0f4b69b 100644
--- a/hal/src/main/native/athena/FRCDriverStation.cpp
+++ b/hal/src/main/native/athena/FRCDriverStation.cpp
@@ -1,22 +1,21 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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 <atomic>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <limits>
+#include <string>
+#include <string_view>
#include <FRC_NetworkCommunication/FRCComm.h>
#include <FRC_NetworkCommunication/NetCommRPCProxy_Occur.h>
+#include <fmt/format.h>
#include <wpi/SafeThread.h>
#include <wpi/condition_variable.h>
#include <wpi/mutex.h>
-#include <wpi/raw_ostream.h>
#include "hal/DriverStation.h"
@@ -70,15 +69,15 @@
joystickNum, &buttons->buttons, &buttons->count);
}
/**
- * Retrieve the Joystick Descriptor for particular slot
- * @param desc [out] descriptor (data transfer object) to fill in. desc is
- * filled in regardless of success. In other words, if descriptor is not
- * available, desc is filled in with default values matching the init-values in
- * Java and C++ Driverstation for when caller requests a too-large joystick
- * index.
+ * Retrieve the Joystick Descriptor for particular slot.
*
+ * @param[out] desc descriptor (data transfer object) to fill in. desc is filled
+ * in regardless of success. In other words, if descriptor is
+ * not available, desc is filled in with default values
+ * matching the init-values in Java and C++ Driverstation for
+ * when caller requests a too-large joystick index.
* @return error code reported from Network Comm back-end. Zero is good,
- * nonzero is bad.
+ * nonzero is bad.
*/
static int32_t HAL_GetJoystickDescriptorInternal(int32_t joystickNum,
HAL_JoystickDescriptor* desc) {
@@ -126,16 +125,14 @@
static wpi::condition_variable* newDSDataAvailableCond;
static int newDSDataAvailableCounter{0};
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeFRCDriverStation() {
static wpi::mutex newMutex;
newDSDataAvailableMutex = &newMutex;
static wpi::condition_variable newCond;
newDSDataAvailableCond = &newCond;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
@@ -161,13 +158,15 @@
auto curTime = std::chrono::steady_clock::now();
int i;
for (i = 0; i < KEEP_MSGS; ++i) {
- if (prevMsg[i] == details) break;
+ if (prevMsg[i] == details) {
+ break;
+ }
}
int retval = 0;
if (i == KEEP_MSGS || (curTime - prevMsgTime[i]) >= std::chrono::seconds(1)) {
- wpi::StringRef detailsRef{details};
- wpi::StringRef locationRef{location};
- wpi::StringRef callStackRef{callStack};
+ std::string_view detailsRef{details};
+ std::string_view locationRef{location};
+ std::string_view callStackRef{callStack};
// 1 tag, 4 timestamp, 2 seqnum
// 2 numOccur, 4 error code, 1 flags, 6 strlen
@@ -203,14 +202,16 @@
newCallStack.c_str());
}
if (printMsg) {
+ fmt::memory_buffer buf;
if (location && location[0] != '\0') {
- wpi::errs() << (isError ? "Error" : "Warning") << " at " << location
- << ": ";
+ fmt::format_to(fmt::appender{buf},
+ "{} at {}: ", isError ? "Error" : "Warning", location);
}
- wpi::errs() << details << "\n";
+ fmt::format_to(fmt::appender{buf}, "{}\n", details);
if (callStack && callStack[0] != '\0') {
- wpi::errs() << callStack << "\n";
+ fmt::format_to(fmt::appender{buf}, "{}\n", callStack);
}
+ std::fwrite(buf.data(), buf.size(), 1, stderr);
}
if (i == KEEP_MSGS) {
// replace the oldest one
@@ -230,7 +231,7 @@
}
int32_t HAL_SendConsoleLine(const char* line) {
- wpi::StringRef lineRef{line};
+ std::string_view lineRef{line};
if (lineRef.size() <= 65535) {
// Send directly
return FRC_NetworkCommunication_sendConsoleLine(line);
@@ -299,15 +300,16 @@
name[0] = '\0';
return name;
} else {
- size_t len = std::strlen(joystickDesc.name);
- char* name = static_cast<char*>(std::malloc(len + 1));
- std::strncpy(name, joystickDesc.name, len);
- name[len] = '\0';
+ const size_t len = std::strlen(joystickDesc.name) + 1;
+ char* name = static_cast<char*>(std::malloc(len));
+ std::memcpy(name, joystickDesc.name, len);
return name;
}
}
-void HAL_FreeJoystickName(char* name) { std::free(name); }
+void HAL_FreeJoystickName(char* name) {
+ std::free(name);
+}
int32_t HAL_GetJoystickAxisType(int32_t joystickNum, int32_t axis) {
HAL_JoystickDescriptor joystickDesc;
@@ -363,21 +365,17 @@
std::scoped_lock lock{*newDSDataAvailableMutex};
int& lastCount = GetThreadLocalLastCount();
int currentCount = newDSDataAvailableCounter;
- if (lastCount == currentCount) return false;
+ if (lastCount == currentCount) {
+ return false;
+ }
lastCount = currentCount;
return true;
}
-/**
- * Waits for the newest DS packet to arrive. Note that this is a blocking call.
- */
-void HAL_WaitForDSData(void) { HAL_WaitForDSDataTimeout(0); }
+void HAL_WaitForDSData(void) {
+ HAL_WaitForDSDataTimeout(0);
+}
-/**
- * Waits for the newest DS packet to arrive. If timeout is <= 0, this will wait
- * forever. Otherwise, it will wait until either a new packet, or the timeout
- * time has passed. Returns true on new data, false on timeout.
- */
HAL_Bool HAL_WaitForDSDataTimeout(double timeout) {
std::unique_lock lock{*newDSDataAvailableMutex};
int& lastCount = GetThreadLocalLastCount();
@@ -409,7 +407,9 @@
static void newDataOccur(uint32_t refNum) {
// Since we could get other values, require our specific handle
// to signal our threads
- if (refNum != refNumber) return;
+ if (refNum != refNumber) {
+ return;
+ }
std::scoped_lock lock{*newDSDataAvailableMutex};
// Notify all threads
++newDSDataAvailableCounter;
@@ -425,11 +425,15 @@
static std::atomic_bool initialized{false};
static wpi::mutex initializeMutex;
// Initial check, as if it's true initialization has finished
- if (initialized) return;
+ if (initialized) {
+ return;
+ }
std::scoped_lock lock(initializeMutex);
// Second check in case another thread was waiting
- if (initialized) return;
+ if (initialized) {
+ return;
+ }
// Set up the occur function internally with NetComm
NetCommRPCProxy_SetOccurFuncPointer(newDataOccur);
@@ -443,6 +447,8 @@
* Releases the DS Mutex to allow proper shutdown of any threads that are
* waiting on it.
*/
-void HAL_ReleaseDSMutex(void) { newDataOccur(refNumber); }
+void HAL_ReleaseDSMutex(void) {
+ newDataOccur(refNumber);
+}
} // extern "C"
diff --git a/hal/src/main/native/athena/HAL.cpp b/hal/src/main/native/athena/HAL.cpp
index 17ef0b9..0b6d05e 100644
--- a/hal/src/main/native/athena/HAL.cpp
+++ b/hal/src/main/native/athena/HAL.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/HAL.h"
@@ -12,6 +9,7 @@
#include <unistd.h>
#include <atomic>
+#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <thread>
@@ -19,13 +17,12 @@
#include <FRC_NetworkCommunication/FRCComm.h>
#include <FRC_NetworkCommunication/LoadOut.h>
#include <FRC_NetworkCommunication/UsageReporting.h>
+#include <fmt/format.h>
#include <wpi/mutex.h>
-#include <wpi/raw_ostream.h>
#include <wpi/timestamp.h>
#include "HALInitializer.h"
#include "HALInternal.h"
-#include "ctre/ctre.h"
#include "hal/ChipObject.h"
#include "hal/DriverStation.h"
#include "hal/Errors.h"
@@ -43,6 +40,8 @@
namespace hal {
namespace init {
void InitializeHAL() {
+ InitializeCTREPCM();
+ InitializeREVPH();
InitializeAddressableLED();
InitializeAccelerometer();
InitializeAnalogAccumulator();
@@ -53,7 +52,6 @@
InitializeAnalogTrigger();
InitializeCAN();
InitializeCANAPI();
- InitializeCompressor();
InitializeConstants();
InitializeCounter();
InitializeDigitalInternal();
@@ -67,14 +65,13 @@
InitializeInterrupts();
InitializeMain();
InitializeNotifier();
- InitializePCMInternal();
- InitializePDP();
+ InitializeCTREPDP();
+ InitializeREVPDH();
InitializePorts();
InitializePower();
InitializePWM();
InitializeRelay();
InitializeSerialPort();
- InitializeSolenoid();
InitializeSPI();
InitializeThreads();
}
@@ -95,14 +92,20 @@
HAL_PortHandle HAL_GetPort(int32_t channel) {
// Dont allow a number that wouldn't fit in a uint8_t
- if (channel < 0 || channel >= 255) return HAL_kInvalidHandle;
+ if (channel < 0 || channel >= 255) {
+ return HAL_kInvalidHandle;
+ }
return createPortHandle(channel, 1);
}
HAL_PortHandle HAL_GetPortWithModule(int32_t module, int32_t channel) {
// Dont allow a number that wouldn't fit in a uint8_t
- if (channel < 0 || channel >= 255) return HAL_kInvalidHandle;
- if (module < 0 || module >= 255) return HAL_kInvalidHandle;
+ if (channel < 0 || channel >= 255) {
+ return HAL_kInvalidHandle;
+ }
+ if (module < 0 || module >= 255) {
+ return HAL_kInvalidHandle;
+ }
return createPortHandle(channel, module);
}
@@ -110,18 +113,6 @@
switch (code) {
case 0:
return "";
- case CTR_RxTimeout:
- return CTR_RxTimeout_MESSAGE;
- case CTR_TxTimeout:
- return CTR_TxTimeout_MESSAGE;
- case CTR_InvalidParamValue:
- return CTR_InvalidParamValue_MESSAGE;
- case CTR_UnexpectedArbId:
- return CTR_UnexpectedArbId_MESSAGE;
- case CTR_TxFailed:
- return CTR_TxFailed_MESSAGE;
- case CTR_SigNotUpdated:
- return CTR_SigNotUpdated_MESSAGE;
case NiFpga_Status_FifoTimeout:
return NiFpga_Status_FifoTimeout_MESSAGE;
case NiFpga_Status_TransferAborted:
@@ -230,12 +221,26 @@
return HAL_CAN_BUFFER_OVERRUN_MESSAGE;
case HAL_LED_CHANNEL_ERROR:
return HAL_LED_CHANNEL_ERROR_MESSAGE;
+ case HAL_INVALID_DMA_STATE:
+ return HAL_INVALID_DMA_STATE_MESSAGE;
+ case HAL_INVALID_DMA_ADDITION:
+ return HAL_INVALID_DMA_ADDITION_MESSAGE;
+ case HAL_USE_LAST_ERROR:
+ return HAL_USE_LAST_ERROR_MESSAGE;
+ case HAL_CONSOLE_OUT_ENABLED_ERROR:
+ return HAL_CONSOLE_OUT_ENABLED_ERROR_MESSAGE;
default:
return "Unknown error status";
}
}
-HAL_RuntimeType HAL_GetRuntimeType(void) { return HAL_Athena; }
+HAL_RuntimeType HAL_GetRuntimeType(void) {
+ nLoadOut::tTargetClass targetClass = nLoadOut::getTargetClass();
+ if (targetClass == nLoadOut::kTargetClass_RoboRIO2) {
+ return HAL_Runtime_RoboRIO2;
+ }
+ return HAL_Runtime_RoboRIO;
+}
int32_t HAL_GetFPGAVersion(int32_t* status) {
if (!global) {
@@ -262,35 +267,41 @@
uint64_t upper1 = global->readLocalTimeUpper(status);
uint32_t lower = global->readLocalTime(status);
uint64_t upper2 = global->readLocalTimeUpper(status);
- if (*status != 0) return 0;
+ if (*status != 0) {
+ return 0;
+ }
if (upper1 != upper2) {
// Rolled over between the lower call, reread lower
lower = global->readLocalTime(status);
- if (*status != 0) return 0;
+ if (*status != 0) {
+ return 0;
+ }
}
return (upper2 << 32) + lower;
}
-uint64_t HAL_ExpandFPGATime(uint32_t unexpanded_lower, int32_t* status) {
+uint64_t HAL_ExpandFPGATime(uint32_t unexpandedLower, int32_t* status) {
// Capture the current FPGA time. This will give us the upper half of the
// clock.
- uint64_t fpga_time = HAL_GetFPGATime(status);
- if (*status != 0) return 0;
+ uint64_t fpgaTime = HAL_GetFPGATime(status);
+ if (*status != 0) {
+ return 0;
+ }
// Now, we need to detect the case where the lower bits rolled over after we
// sampled. In that case, the upper bits will be 1 bigger than they should
// be.
// Break it into lower and upper portions.
- uint32_t lower = fpga_time & 0xffffffffull;
- uint64_t upper = (fpga_time >> 32) & 0xffffffff;
+ uint32_t lower = fpgaTime & 0xffffffffull;
+ uint64_t upper = (fpgaTime >> 32) & 0xffffffff;
// The time was sampled *before* the current time, so roll it back.
- if (lower < unexpanded_lower) {
+ if (lower < unexpandedLower) {
--upper;
}
- return (upper << 32) + static_cast<uint64_t>(unexpanded_lower);
+ return (upper << 32) + static_cast<uint64_t>(unexpandedLower);
}
HAL_Bool HAL_GetFPGAButton(int32_t* status) {
@@ -322,7 +333,9 @@
std::fstream fs;
// By making this both in/out, it won't give us an error if it doesnt exist
fs.open("/var/lock/frc.pid", std::fstream::in | std::fstream::out);
- if (fs.bad()) return false;
+ if (fs.bad()) {
+ return false;
+ }
pid_t pid = 0;
if (!fs.eof() && !fs.fail()) {
@@ -330,18 +343,19 @@
// see if the pid is around, but we don't want to mess with init id=1, or
// ourselves
if (pid >= 2 && kill(pid, 0) == 0 && pid != getpid()) {
- wpi::outs() << "Killing previously running FRC program...\n";
+ std::puts("Killing previously running FRC program...");
kill(pid, SIGTERM); // try to kill it
std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
if (kill(pid, 0) == 0) {
// still not successful
- wpi::outs() << "FRC pid " << pid << " did not die within " << timeout
- << "ms. Force killing with kill -9\n";
+ fmt::print(
+ "FRC pid {} did not die within {} ms. Force killing with kill -9\n",
+ pid, timeout);
// Force kill -9
auto forceKill = kill(pid, SIGKILL);
if (forceKill != 0) {
auto errorMsg = std::strerror(forceKill);
- wpi::outs() << "Kill -9 error: " << errorMsg << "\n";
+ fmt::print("Kill -9 error: {}\n", errorMsg);
}
// Give a bit of time for the kill to take place
std::this_thread::sleep_for(std::chrono::milliseconds(250));
@@ -362,11 +376,15 @@
static std::atomic_bool initialized{false};
static wpi::mutex initializeMutex;
// Initial check, as if it's true initialization has finished
- if (initialized) return true;
+ if (initialized) {
+ return true;
+ }
std::scoped_lock lock(initializeMutex);
// Second check in case another thread was waiting
- if (initialized) return true;
+ if (initialized) {
+ return true;
+ }
hal::init::InitializeHAL();
@@ -374,7 +392,6 @@
setlinebuf(stdin);
setlinebuf(stdout);
- wpi::outs().SetUnbuffered();
prctl(PR_SET_PDEATHSIG, SIGTERM);
@@ -397,7 +414,9 @@
global.reset(tGlobal::create(&status));
watchdog.reset(tSysWatchdog::create(&status));
- if (status != 0) return false;
+ if (status != 0) {
+ return false;
+ }
HAL_InitializeDriverStation();
@@ -406,11 +425,11 @@
int32_t status = 0;
uint64_t rv = HAL_GetFPGATime(&status);
if (status != 0) {
- wpi::errs()
- << "Call to HAL_GetFPGATime failed in wpi::Now() with status "
- << status
- << ". Initialization might have failed. Time will not be correct\n";
- wpi::errs().flush();
+ 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;
@@ -422,6 +441,10 @@
void HAL_Shutdown(void) {}
+void HAL_SimPeriodicBefore(void) {}
+
+void HAL_SimPeriodicAfter(void) {}
+
int64_t HAL_Report(int32_t resource, int32_t instanceNumber, int32_t context,
const char* feature) {
if (feature == nullptr) {
@@ -432,10 +455,4 @@
resource, instanceNumber, context, feature);
}
-// TODO: HACKS
-// No need for header definitions, as we should not run from user code.
-void NumericArrayResize(void) {}
-void RTSetCleanupProc(void) {}
-void EDVR_CreateReference(void) {}
-
} // extern "C"
diff --git a/hal/src/main/native/athena/HALInitializer.cpp b/hal/src/main/native/athena/HALInitializer.cpp
index 5c2242b..50cc9ab 100644
--- a/hal/src/main/native/athena/HALInitializer.cpp
+++ b/hal/src/main/native/athena/HALInitializer.cpp
@@ -1,17 +1,14 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2018-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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 "HALInitializer.h"
#include "hal/HALBase.h"
-namespace hal {
-namespace init {
+namespace hal::init {
std::atomic_bool HAL_IsInitialized{false};
-void RunInitialize() { HAL_Initialize(500, 0); }
-} // namespace init
-} // namespace hal
+void RunInitialize() {
+ HAL_Initialize(500, 0);
+}
+} // namespace hal::init
diff --git a/hal/src/main/native/athena/HALInitializer.h b/hal/src/main/native/athena/HALInitializer.h
index c54660f..182ab5b 100644
--- a/hal/src/main/native/athena/HALInitializer.h
+++ b/hal/src/main/native/athena/HALInitializer.h
@@ -1,23 +1,23 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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 <atomic>
-namespace hal {
-namespace init {
+namespace hal::init {
extern std::atomic_bool HAL_IsInitialized;
extern void RunInitialize();
-static inline void CheckInit() {
- if (HAL_IsInitialized.load(std::memory_order_relaxed)) return;
+inline void CheckInit() {
+ if (HAL_IsInitialized.load(std::memory_order_relaxed)) {
+ return;
+ }
RunInitialize();
}
+extern void InitializeCTREPCM();
+extern void InitializeREVPH();
extern void InitializeAccelerometer();
extern void InitializeAddressableLED();
extern void InitializeAnalogAccumulator();
@@ -28,7 +28,6 @@
extern void InitializeAnalogTrigger();
extern void InitializeCAN();
extern void InitializeCANAPI();
-extern void InitializeCompressor();
extern void InitializeConstants();
extern void InitializeCounter();
extern void InitializeDigitalInternal();
@@ -43,15 +42,13 @@
extern void InitializeInterrupts();
extern void InitializeMain();
extern void InitializeNotifier();
-extern void InitializePCMInternal();
-extern void InitializePDP();
+extern void InitializeCTREPDP();
+extern void InitializeREVPDH();
extern void InitializePorts();
extern void InitializePower();
extern void InitializePWM();
extern void InitializeRelay();
extern void InitializeSerialPort();
-extern void InitializeSolenoid();
extern void InitializeSPI();
extern void InitializeThreads();
-} // namespace init
-} // namespace hal
+} // namespace hal::init
diff --git a/hal/src/main/native/athena/HALInternal.h b/hal/src/main/native/athena/HALInternal.h
index e3033bf..64a0dca 100644
--- a/hal/src/main/native/athena/HALInternal.h
+++ b/hal/src/main/native/athena/HALInternal.h
@@ -1,15 +1,20 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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>
+#include <string_view>
+
namespace hal {
void ReleaseFPGAInterrupt(int32_t interruptNumber);
-
+void SetLastError(int32_t* status, std::string_view value);
+void SetLastErrorIndexOutOfRange(int32_t* status, std::string_view message,
+ int32_t minimum, int32_t maximum,
+ int32_t channel);
+void SetLastErrorPreviouslyAllocated(int32_t* status, std::string_view message,
+ int32_t channel,
+ std::string_view previousAllocation);
} // namespace hal
diff --git a/hal/src/main/native/athena/I2C.cpp b/hal/src/main/native/athena/I2C.cpp
index b72e25e..93e280e 100644
--- a/hal/src/main/native/athena/I2C.cpp
+++ b/hal/src/main/native/athena/I2C.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/I2C.h"
@@ -15,8 +12,11 @@
#include <cstring>
+#include <fmt/format.h>
+
#include "DigitalInternal.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "hal/DIO.h"
#include "hal/HAL.h"
@@ -33,44 +33,50 @@
static HAL_DigitalHandle i2CMXPDigitalHandle1{HAL_kInvalidHandle};
static HAL_DigitalHandle i2CMXPDigitalHandle2{HAL_kInvalidHandle};
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeI2C() {}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) {
hal::init::CheckInit();
initializeDigital(status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
if (port < 0 || port > 1) {
- // Set port out of range error here
+ *status = RESOURCE_OUT_OF_RANGE;
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for I2C", 0, 1,
+ port);
return;
}
if (port == HAL_I2C_kOnboard) {
std::scoped_lock lock(digitalI2COnBoardMutex);
i2COnboardObjCount++;
- if (i2COnboardObjCount > 1) return;
+ if (i2COnboardObjCount > 1) {
+ return;
+ }
int handle = open("/dev/i2c-2", O_RDWR);
if (handle < 0) {
- std::printf("Failed to open onboard i2c bus: %s\n", std::strerror(errno));
+ fmt::print("Failed to open onboard i2c bus: {}\n", std::strerror(errno));
return;
}
i2COnBoardHandle = handle;
} else {
std::scoped_lock lock(digitalI2CMXPMutex);
i2CMXPObjCount++;
- if (i2CMXPObjCount > 1) return;
+ if (i2CMXPObjCount > 1) {
+ return;
+ }
if ((i2CMXPDigitalHandle1 = HAL_InitializeDIOPort(
- HAL_GetPort(24), false, status)) == HAL_kInvalidHandle) {
+ HAL_GetPort(24), false, nullptr, status)) == HAL_kInvalidHandle) {
return;
}
if ((i2CMXPDigitalHandle2 = HAL_InitializeDIOPort(
- HAL_GetPort(25), false, status)) == HAL_kInvalidHandle) {
+ HAL_GetPort(25), false, nullptr, status)) == HAL_kInvalidHandle) {
HAL_FreeDIOPort(i2CMXPDigitalHandle1); // free the first port allocated
return;
}
@@ -78,7 +84,7 @@
digitalSystem->readEnableMXPSpecialFunction(status) | 0xC000, status);
int handle = open("/dev/i2c-1", O_RDWR);
if (handle < 0) {
- std::printf("Failed to open MXP i2c bus: %s\n", std::strerror(errno));
+ fmt::print("Failed to open MXP i2c bus: {}\n", std::strerror(errno));
return;
}
i2CMXPHandle = handle;
@@ -89,7 +95,9 @@
const uint8_t* dataToSend, int32_t sendSize,
uint8_t* dataReceived, int32_t receiveSize) {
if (port < 0 || port > 1) {
- // Set port out of range error here
+ int32_t status = 0;
+ hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, 1,
+ port);
return -1;
}
@@ -119,7 +127,9 @@
int32_t HAL_WriteI2C(HAL_I2CPort port, int32_t deviceAddress,
const uint8_t* dataToSend, int32_t sendSize) {
if (port < 0 || port > 1) {
- // Set port out of range error here
+ int32_t status = 0;
+ hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, 1,
+ port);
return -1;
}
@@ -145,7 +155,9 @@
int32_t HAL_ReadI2C(HAL_I2CPort port, int32_t deviceAddress, uint8_t* buffer,
int32_t count) {
if (port < 0 || port > 1) {
- // Set port out of range error here
+ int32_t status = 0;
+ hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, 1,
+ port);
return -1;
}
@@ -170,7 +182,9 @@
void HAL_CloseI2C(HAL_I2CPort port) {
if (port < 0 || port > 1) {
- // Set port out of range error here
+ int32_t status = 0;
+ hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, 1,
+ port);
return;
}
diff --git a/hal/src/main/native/athena/Interrupts.cpp b/hal/src/main/native/athena/Interrupts.cpp
index a330e3c..943a1aa 100644
--- a/hal/src/main/native/athena/Interrupts.cpp
+++ b/hal/src/main/native/athena/Interrupts.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/Interrupts.h"
@@ -24,79 +21,29 @@
using namespace hal;
namespace {
-// Safe thread to allow callbacks to run on their own thread
-class InterruptThread : public wpi::SafeThread {
- public:
- void Main() {
- std::unique_lock lock(m_mutex);
- while (m_active) {
- m_cond.wait(lock, [&] { return !m_active || m_notify; });
- if (!m_active) break;
- m_notify = false;
- HAL_InterruptHandlerFunction handler = m_handler;
- uint32_t mask = m_mask;
- void* param = m_param;
- lock.unlock(); // don't hold mutex during callback execution
- handler(mask, param);
- lock.lock();
- }
- }
-
- bool m_notify = false;
- HAL_InterruptHandlerFunction m_handler;
- void* m_param;
- uint32_t m_mask;
-};
-
-class InterruptThreadOwner : public wpi::SafeThreadOwner<InterruptThread> {
- public:
- void SetFunc(HAL_InterruptHandlerFunction handler, void* param) {
- auto thr = GetThread();
- if (!thr) return;
- thr->m_handler = handler;
- thr->m_param = param;
- }
-
- void Notify(uint32_t mask) {
- auto thr = GetThread();
- if (!thr) return;
- thr->m_mask = mask;
- thr->m_notify = true;
- thr->m_cond.notify_one();
- }
-};
struct Interrupt {
std::unique_ptr<tInterrupt> anInterrupt;
std::unique_ptr<tInterruptManager> manager;
- std::unique_ptr<InterruptThreadOwner> threadOwner = nullptr;
- void* param = nullptr;
};
} // namespace
-static void threadedInterruptHandler(uint32_t mask, void* param) {
- static_cast<InterruptThreadOwner*>(param)->Notify(mask);
-}
-
static LimitedHandleResource<HAL_InterruptHandle, Interrupt, kNumInterrupts,
HAL_HandleEnum::Interrupt>* interruptHandles;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeInterrupts() {
static LimitedHandleResource<HAL_InterruptHandle, Interrupt, kNumInterrupts,
HAL_HandleEnum::Interrupt>
iH;
interruptHandles = &iH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
-HAL_InterruptHandle HAL_InitializeInterrupts(HAL_Bool watcher,
- int32_t* status) {
+HAL_InterruptHandle HAL_InitializeInterrupts(int32_t* status) {
hal::init::CheckInit();
HAL_InterruptHandle handle = interruptHandles->Allocate();
if (handle == HAL_kInvalidHandle) {
@@ -109,24 +56,16 @@
anInterrupt->anInterrupt.reset(tInterrupt::create(interruptIndex, status));
anInterrupt->anInterrupt->writeConfig_WaitForAck(false, status);
anInterrupt->manager = std::make_unique<tInterruptManager>(
- (1u << interruptIndex) | (1u << (interruptIndex + 8u)), watcher, status);
+ (1u << interruptIndex) | (1u << (interruptIndex + 8u)), true, status);
return handle;
}
-void* HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle,
- int32_t* status) {
+void HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle) {
auto anInterrupt = interruptHandles->Get(interruptHandle);
interruptHandles->Free(interruptHandle);
if (anInterrupt == nullptr) {
- return nullptr;
+ return;
}
-
- if (anInterrupt->manager->isEnabled(status)) {
- anInterrupt->manager->disable(status);
- }
-
- void* param = anInterrupt->param;
- return param;
}
int64_t HAL_WaitForInterrupt(HAL_InterruptHandle interruptHandle,
@@ -151,31 +90,6 @@
return result;
}
-void HAL_EnableInterrupts(HAL_InterruptHandle interruptHandle,
- int32_t* status) {
- auto anInterrupt = interruptHandles->Get(interruptHandle);
- if (anInterrupt == nullptr) {
- *status = HAL_HANDLE_ERROR;
- return;
- }
-
- if (!anInterrupt->manager->isEnabled(status)) {
- anInterrupt->manager->enable(status);
- }
-}
-
-void HAL_DisableInterrupts(HAL_InterruptHandle interruptHandle,
- int32_t* status) {
- auto anInterrupt = interruptHandles->Get(interruptHandle);
- if (anInterrupt == nullptr) {
- *status = HAL_HANDLE_ERROR;
- return;
- }
- if (anInterrupt->manager->isEnabled(status)) {
- anInterrupt->manager->disable(status);
- }
-}
-
int64_t HAL_ReadInterruptRisingTimestamp(HAL_InterruptHandle interruptHandle,
int32_t* status) {
auto anInterrupt = interruptHandles->Get(interruptHandle);
@@ -224,40 +138,6 @@
anInterrupt->anInterrupt->writeConfig_Source_Module(routingModule, status);
}
-void HAL_AttachInterruptHandler(HAL_InterruptHandle interruptHandle,
- HAL_InterruptHandlerFunction handler,
- void* param, int32_t* status) {
- auto anInterrupt = interruptHandles->Get(interruptHandle);
- if (anInterrupt == nullptr) {
- *status = HAL_HANDLE_ERROR;
- return;
- }
- anInterrupt->manager->registerHandler(handler, param, status);
- anInterrupt->param = param;
-}
-
-void HAL_AttachInterruptHandlerThreaded(HAL_InterruptHandle interrupt_handle,
- HAL_InterruptHandlerFunction handler,
- void* param, int32_t* status) {
- auto anInterrupt = interruptHandles->Get(interrupt_handle);
- if (anInterrupt == nullptr) {
- *status = HAL_HANDLE_ERROR;
- return;
- }
-
- anInterrupt->threadOwner = std::make_unique<InterruptThreadOwner>();
- anInterrupt->threadOwner->Start();
- anInterrupt->threadOwner->SetFunc(handler, param);
-
- HAL_AttachInterruptHandler(interrupt_handle, threadedInterruptHandler,
- anInterrupt->threadOwner.get(), status);
-
- if (*status != 0) {
- anInterrupt->threadOwner = nullptr;
- }
- anInterrupt->param = param;
-}
-
void HAL_SetInterruptUpSourceEdge(HAL_InterruptHandle interruptHandle,
HAL_Bool risingEdge, HAL_Bool fallingEdge,
int32_t* status) {
diff --git a/hal/src/main/native/athena/Notifier.cpp b/hal/src/main/native/athena/Notifier.cpp
index 905c440..d684031 100644
--- a/hal/src/main/native/athena/Notifier.cpp
+++ b/hal/src/main/native/athena/Notifier.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/Notifier.h"
@@ -12,6 +9,7 @@
#include <memory>
#include <thread>
+#include <fmt/core.h>
#include <wpi/condition_variable.h>
#include <wpi/mutex.h>
@@ -20,6 +18,7 @@
#include "hal/ChipObject.h"
#include "hal/Errors.h"
#include "hal/HAL.h"
+#include "hal/Threads.h"
#include "hal/handles/UnlimitedHandleResource.h"
using namespace hal;
@@ -29,6 +28,8 @@
static wpi::mutex notifierMutex;
static std::unique_ptr<tAlarm> notifierAlarm;
static std::thread notifierThread;
+static HAL_Bool notifierThreadRealTime = false;
+static int32_t notifierThreadPriority = 0;
static uint64_t closestTrigger{UINT64_MAX};
namespace {
@@ -78,8 +79,12 @@
// process all notifiers
notifierHandles->ForEach([&](HAL_NotifierHandle handle, Notifier* notifier) {
- if (notifier->triggerTime == UINT64_MAX) return;
- if (currentTime == 0) currentTime = HAL_GetFPGATime(&status);
+ if (notifier->triggerTime == UINT64_MAX) {
+ return;
+ }
+ if (currentTime == 0) {
+ currentTime = HAL_GetFPGATime(&status);
+ }
std::unique_lock lock(notifier->mutex);
if (notifier->triggerTime < currentTime) {
notifier->triggerTime = UINT64_MAX;
@@ -105,41 +110,61 @@
tInterruptManager manager{1 << kTimerInterruptNumber, true, &status};
while (notifierRunning) {
auto triggeredMask = manager.watch(10000, false, &status);
- if (!notifierRunning) break;
- if (triggeredMask == 0) continue;
+ if (!notifierRunning) {
+ break;
+ }
+ if (triggeredMask == 0)
+ continue;
alarmCallback();
}
}
static void cleanupNotifierAtExit() {
int32_t status = 0;
- if (notifierAlarm) notifierAlarm->writeEnable(false, &status);
+ if (notifierAlarm)
+ notifierAlarm->writeEnable(false, &status);
notifierAlarm = nullptr;
notifierRunning = false;
hal::ReleaseFPGAInterrupt(kTimerInterruptNumber);
- if (notifierThread.joinable()) notifierThread.join();
+ if (notifierThread.joinable()) {
+ notifierThread.join();
+ }
}
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeNotifier() {
static NotifierHandleContainer nH;
notifierHandles = &nH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
HAL_NotifierHandle HAL_InitializeNotifier(int32_t* status) {
hal::init::CheckInit();
- if (!notifierAtexitRegistered.test_and_set())
+ if (!notifierAtexitRegistered.test_and_set()) {
std::atexit(cleanupNotifierAtExit);
+ }
if (notifierRefCount.fetch_add(1) == 0) {
std::scoped_lock lock(notifierMutex);
notifierRunning = true;
notifierThread = std::thread(notifierThreadMain);
+
+ auto native = notifierThread.native_handle();
+ HAL_SetThreadPriority(&native, notifierThreadRealTime,
+ notifierThreadPriority, status);
+ if (*status == HAL_THREAD_PRIORITY_ERROR) {
+ *status = 0;
+ fmt::print("{}: HAL Notifier thread\n",
+ HAL_THREAD_PRIORITY_ERROR_MESSAGE);
+ }
+ if (*status == HAL_THREAD_PRIORITY_RANGE_ERROR) {
+ *status = 0;
+ fmt::print("{}: HAL Notifier thread\n",
+ HAL_THREAD_PRIORITY_RANGE_ERROR_MESSAGE);
+ }
+
notifierAlarm.reset(tAlarm::create(status));
}
@@ -152,12 +177,26 @@
return handle;
}
+HAL_Bool HAL_SetNotifierThreadPriority(HAL_Bool realTime, int32_t priority,
+ int32_t* status) {
+ std::scoped_lock lock(notifierMutex);
+ notifierThreadRealTime = realTime;
+ notifierThreadPriority = priority;
+ if (notifierThread.joinable()) {
+ auto native = notifierThread.native_handle();
+ return HAL_SetThreadPriority(&native, realTime, priority, status);
+ } else {
+ return true;
+ }
+}
+
void HAL_SetNotifierName(HAL_NotifierHandle notifierHandle, const char* name,
int32_t* status) {}
void HAL_StopNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
auto notifier = notifierHandles->Get(notifierHandle);
- if (!notifier) return;
+ if (!notifier)
+ return;
{
std::scoped_lock lock(notifier->mutex);
@@ -170,7 +209,8 @@
void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
auto notifier = notifierHandles->Free(notifierHandle);
- if (!notifier) return;
+ if (!notifier)
+ return;
// Just in case HAL_StopNotifier() wasn't called...
{
@@ -187,10 +227,13 @@
// here (the atomic fetch_sub will prevent multiple parallel entries
// into this function)
- if (notifierAlarm) notifierAlarm->writeEnable(false, status);
+ if (notifierAlarm)
+ notifierAlarm->writeEnable(false, status);
notifierRunning = false;
hal::ReleaseFPGAInterrupt(kTimerInterruptNumber);
- if (notifierThread.joinable()) notifierThread.join();
+ if (notifierThread.joinable()) {
+ notifierThread.join();
+ }
std::scoped_lock lock(notifierMutex);
notifierAlarm = nullptr;
@@ -201,7 +244,8 @@
void HAL_UpdateNotifierAlarm(HAL_NotifierHandle notifierHandle,
uint64_t triggerTime, int32_t* status) {
auto notifier = notifierHandles->Get(notifierHandle);
- if (!notifier) return;
+ if (!notifier)
+ return;
{
std::scoped_lock lock(notifier->mutex);
@@ -218,14 +262,16 @@
notifierAlarm->writeTriggerTime(static_cast<uint32_t>(closestTrigger),
status);
// Enable the alarm.
- if (!wasActive) notifierAlarm->writeEnable(true, status);
+ if (!wasActive)
+ notifierAlarm->writeEnable(true, status);
}
}
void HAL_CancelNotifierAlarm(HAL_NotifierHandle notifierHandle,
int32_t* status) {
auto notifier = notifierHandles->Get(notifierHandle);
- if (!notifier) return;
+ if (!notifier)
+ return;
{
std::scoped_lock lock(notifier->mutex);
@@ -236,7 +282,8 @@
uint64_t HAL_WaitForNotifierAlarm(HAL_NotifierHandle notifierHandle,
int32_t* status) {
auto notifier = notifierHandles->Get(notifierHandle);
- if (!notifier) return 0;
+ if (!notifier)
+ return 0;
std::unique_lock lock(notifier->mutex);
notifier->cond.wait(lock, [&] {
return !notifier->active || notifier->triggeredTime != UINT64_MAX;
diff --git a/hal/src/main/native/athena/PCMInternal.cpp b/hal/src/main/native/athena/PCMInternal.cpp
deleted file mode 100644
index c81dc1a..0000000
--- a/hal/src/main/native/athena/PCMInternal.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
-
-#include "PCMInternal.h"
-
-#include "HALInitializer.h"
-#include "hal/Errors.h"
-#include "hal/Solenoid.h"
-
-namespace hal {
-
-std::unique_ptr<PCM> PCM_modules[kNumPCMModules];
-
-namespace init {
-void InitializePCMInternal() {
- for (int i = 0; i < kNumPCMModules; i++) {
- PCM_modules[i] = nullptr;
- }
-}
-} // namespace init
-
-void initializePCM(int32_t module, int32_t* status) {
- hal::init::CheckInit();
- if (!HAL_CheckSolenoidModule(module)) {
- *status = RESOURCE_OUT_OF_RANGE;
- return;
- }
- if (!PCM_modules[module]) {
- PCM_modules[module] = std::make_unique<PCM>(module);
- }
-}
-
-} // namespace hal
diff --git a/hal/src/main/native/athena/PCMInternal.h b/hal/src/main/native/athena/PCMInternal.h
deleted file mode 100644
index a9d076c..0000000
--- a/hal/src/main/native/athena/PCMInternal.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
-
-#pragma once
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "PortsInternal.h"
-#include "ctre/PCM.h"
-#include "hal/Errors.h"
-#include "hal/Solenoid.h"
-
-namespace hal {
-
-extern std::unique_ptr<PCM> PCM_modules[kNumPCMModules];
-
-static inline bool checkPCMInit(int32_t module, int32_t* status) {
- if (!HAL_CheckSolenoidModule(module)) {
- *status = RESOURCE_OUT_OF_RANGE;
- return false;
- }
- if (!PCM_modules[module]) {
- *status = INCOMPATIBLE_STATE;
- return false;
- }
- return true;
-}
-
-void initializePCM(int32_t module, int32_t* status);
-
-} // namespace hal
diff --git a/hal/src/main/native/athena/PWM.cpp b/hal/src/main/native/athena/PWM.cpp
index a3b141c..19a3b83 100644
--- a/hal/src/main/native/athena/PWM.cpp
+++ b/hal/src/main/native/athena/PWM.cpp
@@ -1,20 +1,18 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/PWM.h"
+#include <algorithm>
#include <cmath>
+#include <cstdio>
#include <thread>
-#include <wpi/raw_ostream.h>
-
#include "ConstantsInternal.h"
#include "DigitalInternal.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/cpp/fpga_clock.h"
#include "hal/handles/HandlesInternal.h"
@@ -61,24 +59,27 @@
return GetMaxPositivePwm(port) - GetMinNegativePwm(port);
} ///< The scale for positions.
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializePWM() {}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
HAL_DigitalHandle HAL_InitializePWMPort(HAL_PortHandle portHandle,
+ const char* allocationLocation,
int32_t* status) {
hal::init::CheckInit();
initializeDigital(status);
- if (*status != 0) return HAL_kInvalidHandle;
+ if (*status != 0) {
+ return HAL_kInvalidHandle;
+ }
int16_t channel = getPortHandleChannel(portHandle);
if (channel == InvalidHandleIndex || channel >= kNumPWMChannels) {
- *status = PARAMETER_OUT_OF_RANGE;
+ *status = RESOURCE_OUT_OF_RANGE;
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for PWM", 0,
+ kNumPWMChannels, channel);
return HAL_kInvalidHandle;
}
@@ -90,16 +91,20 @@
channel = remapMXPPWMChannel(channel) + 10; // remap MXP to proper channel
}
- auto handle =
- digitalChannelHandles->Allocate(channel, HAL_HandleEnum::PWM, status);
+ HAL_DigitalHandle handle;
- if (*status != 0)
+ auto port = digitalChannelHandles->Allocate(channel, HAL_HandleEnum::PWM,
+ &handle, status);
+
+ if (*status != 0) {
+ if (port) {
+ hal::SetLastErrorPreviouslyAllocated(status, "PWM or DIO", origChannel,
+ port->previousAllocation);
+ } else {
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for PWM", 0,
+ kNumPWMChannels, origChannel);
+ }
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
-
- auto port = digitalChannelHandles->Get(handle, HAL_HandleEnum::PWM);
- if (port == nullptr) { // would only occur on thread issue.
- *status = HAL_HANDLE_ERROR;
- return HAL_kInvalidHandle;
}
port->channel = origChannel;
@@ -115,6 +120,8 @@
// Defaults to allow an always valid config.
HAL_SetPWMConfig(handle, 2.0, 1.501, 1.5, 1.499, 1.0, status);
+ port->previousAllocation = allocationLocation ? allocationLocation : "";
+
return handle;
}
void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
@@ -131,8 +138,8 @@
while (port.use_count() != 1) {
auto current = hal::fpga_clock::now();
if (start + std::chrono::seconds(1) < current) {
- wpi::outs() << "PWM handle free timeout\n";
- wpi::outs().flush();
+ std::puts("PWM handle free timeout");
+ std::fflush(stdout);
break;
}
std::this_thread::yield();
@@ -163,7 +170,9 @@
// calculate the loop time in milliseconds
double loopTime =
HAL_GetPWMLoopTiming(status) / (kSystemClockTicksPerMicrosecond * 1e3);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
int32_t maxPwm = static_cast<int32_t>((max - kDefaultPwmCenter) / loopTime +
kDefaultPwmStepsDown - 1);
@@ -277,13 +286,13 @@
if (speed == 0.0) {
rawValue = GetCenterPwm(dPort);
} else if (speed > 0.0) {
- rawValue = static_cast<int32_t>(
- speed * static_cast<double>(GetPositiveScaleFactor(dPort)) +
- static_cast<double>(GetMinPositivePwm(dPort)) + 0.5);
+ rawValue =
+ std::lround(speed * static_cast<double>(GetPositiveScaleFactor(dPort)) +
+ static_cast<double>(GetMinPositivePwm(dPort)));
} else {
- rawValue = static_cast<int32_t>(
- speed * static_cast<double>(GetNegativeScaleFactor(dPort)) +
- static_cast<double>(GetMaxNegativePwm(dPort)) + 0.5);
+ rawValue =
+ std::lround(speed * static_cast<double>(GetNegativeScaleFactor(dPort)) +
+ static_cast<double>(GetMaxNegativePwm(dPort)));
}
if (!((rawValue >= GetMinNegativePwm(dPort)) &&
@@ -359,7 +368,9 @@
}
int32_t value = HAL_GetPWMRaw(pwmPortHandle, status);
- if (*status != 0) return 0;
+ if (*status != 0) {
+ return 0;
+ }
DigitalPort* dPort = port.get();
if (value == kPwmDisabled) {
@@ -391,7 +402,9 @@
}
int32_t value = HAL_GetPWMRaw(pwmPortHandle, status);
- if (*status != 0) return 0;
+ if (*status != 0) {
+ return 0;
+ }
DigitalPort* dPort = port.get();
if (value < GetMinNegativePwm(dPort)) {
@@ -433,22 +446,30 @@
int32_t HAL_GetPWMLoopTiming(int32_t* status) {
initializeDigital(status);
- if (*status != 0) return 0;
+ if (*status != 0) {
+ return 0;
+ }
return pwmSystem->readLoopTiming(status);
}
uint64_t HAL_GetPWMCycleStartTime(int32_t* status) {
initializeDigital(status);
- if (*status != 0) return 0;
+ if (*status != 0) {
+ return 0;
+ }
uint64_t upper1 = pwmSystem->readCycleStartTimeUpper(status);
uint32_t lower = pwmSystem->readCycleStartTime(status);
uint64_t upper2 = pwmSystem->readCycleStartTimeUpper(status);
- if (*status != 0) return 0;
+ if (*status != 0) {
+ return 0;
+ }
if (upper1 != upper2) {
// Rolled over between the lower call, reread lower
lower = pwmSystem->readCycleStartTime(status);
- if (*status != 0) return 0;
+ if (*status != 0) {
+ return 0;
+ }
}
return (upper2 << 32) + lower;
}
diff --git a/hal/src/main/native/athena/Ports.cpp b/hal/src/main/native/athena/Ports.cpp
index 47bd400..d27ecbd 100644
--- a/hal/src/main/native/athena/Ports.cpp
+++ b/hal/src/main/native/athena/Ports.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/Ports.h"
@@ -11,33 +8,83 @@
using namespace hal;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializePorts() {}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
-int32_t HAL_GetNumAccumulators(void) { return kNumAccumulators; }
-int32_t HAL_GetNumAnalogTriggers(void) { return kNumAnalogTriggers; }
-int32_t HAL_GetNumAnalogInputs(void) { return kNumAnalogInputs; }
-int32_t HAL_GetNumAnalogOutputs(void) { return kNumAnalogOutputs; }
-int32_t HAL_GetNumCounters(void) { return kNumCounters; }
-int32_t HAL_GetNumDigitalHeaders(void) { return kNumDigitalHeaders; }
-int32_t HAL_GetNumPWMHeaders(void) { return kNumPWMHeaders; }
-int32_t HAL_GetNumDigitalChannels(void) { return kNumDigitalChannels; }
-int32_t HAL_GetNumPWMChannels(void) { return kNumPWMChannels; }
-int32_t HAL_GetNumDigitalPWMOutputs(void) { return kNumDigitalPWMOutputs; }
-int32_t HAL_GetNumEncoders(void) { return kNumEncoders; }
-int32_t HAL_GetNumInterrupts(void) { return kNumInterrupts; }
-int32_t HAL_GetNumRelayChannels(void) { return kNumRelayChannels; }
-int32_t HAL_GetNumRelayHeaders(void) { return kNumRelayHeaders; }
-int32_t HAL_GetNumPCMModules(void) { return kNumPCMModules; }
-int32_t HAL_GetNumSolenoidChannels(void) { return kNumSolenoidChannels; }
-int32_t HAL_GetNumPDPModules(void) { return kNumPDPModules; }
-int32_t HAL_GetNumPDPChannels(void) { return kNumPDPChannels; }
-int32_t HAL_GetNumDutyCycles(void) { return kNumDutyCycles; }
-int32_t HAL_GetNumAddressableLEDs(void) { return kNumAddressableLEDs; }
+int32_t HAL_GetNumAccumulators(void) {
+ return kNumAccumulators;
+}
+int32_t HAL_GetNumAnalogTriggers(void) {
+ return kNumAnalogTriggers;
+}
+int32_t HAL_GetNumAnalogInputs(void) {
+ return kNumAnalogInputs;
+}
+int32_t HAL_GetNumAnalogOutputs(void) {
+ return kNumAnalogOutputs;
+}
+int32_t HAL_GetNumCounters(void) {
+ return kNumCounters;
+}
+int32_t HAL_GetNumDigitalHeaders(void) {
+ return kNumDigitalHeaders;
+}
+int32_t HAL_GetNumPWMHeaders(void) {
+ return kNumPWMHeaders;
+}
+int32_t HAL_GetNumDigitalChannels(void) {
+ return kNumDigitalChannels;
+}
+int32_t HAL_GetNumPWMChannels(void) {
+ return kNumPWMChannels;
+}
+int32_t HAL_GetNumDigitalPWMOutputs(void) {
+ return kNumDigitalPWMOutputs;
+}
+int32_t HAL_GetNumEncoders(void) {
+ return kNumEncoders;
+}
+int32_t HAL_GetNumInterrupts(void) {
+ return kNumInterrupts;
+}
+int32_t HAL_GetNumRelayChannels(void) {
+ return kNumRelayChannels;
+}
+int32_t HAL_GetNumRelayHeaders(void) {
+ return kNumRelayHeaders;
+}
+int32_t HAL_GetNumCTREPCMModules(void) {
+ return kNumCTREPCMModules;
+}
+int32_t HAL_GetNumCTRESolenoidChannels(void) {
+ return kNumCTRESolenoidChannels;
+}
+int32_t HAL_GetNumCTREPDPModules(void) {
+ return kNumCTREPDPModules;
+}
+int32_t HAL_GetNumCTREPDPChannels(void) {
+ return kNumCTREPDPChannels;
+}
+int32_t HAL_GetNumREVPDHModules(void) {
+ return kNumREVPDHModules;
+}
+int32_t HAL_GetNumREVPDHChannels(void) {
+ return kNumREVPDHChannels;
+}
+int32_t HAL_GetNumREVPHModules(void) {
+ return kNumREVPHModules;
+}
+int32_t HAL_GetNumREVPHChannels(void) {
+ return kNumREVPHChannels;
+}
+int32_t HAL_GetNumDutyCycles(void) {
+ return kNumDutyCycles;
+}
+int32_t HAL_GetNumAddressableLEDs(void) {
+ return kNumAddressableLEDs;
+}
} // extern "C"
diff --git a/hal/src/main/native/athena/PortsInternal.h b/hal/src/main/native/athena/PortsInternal.h
index 98fc690..18ce569 100644
--- a/hal/src/main/native/athena/PortsInternal.h
+++ b/hal/src/main/native/athena/PortsInternal.h
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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
@@ -31,11 +28,15 @@
constexpr int32_t kNumInterrupts = tInterrupt::kNumSystems;
constexpr int32_t kNumRelayChannels = 8;
constexpr int32_t kNumRelayHeaders = kNumRelayChannels / 2;
-constexpr int32_t kNumPCMModules = 63;
-constexpr int32_t kNumSolenoidChannels = 8;
-constexpr int32_t kNumPDPModules = 63;
-constexpr int32_t kNumPDPChannels = 16;
+constexpr int32_t kNumCTREPCMModules = 63;
+constexpr int32_t kNumCTRESolenoidChannels = 8;
+constexpr int32_t kNumCTREPDPModules = 63;
+constexpr int32_t kNumCTREPDPChannels = 16;
+constexpr int32_t kNumREVPDHModules = 63;
+constexpr int32_t kNumREVPDHChannels = 24;
constexpr int32_t kNumDutyCycles = tDutyCycle::kNumSystems;
constexpr int32_t kNumAddressableLEDs = tLED::kNumSystems;
+constexpr int32_t kNumREVPHModules = 63;
+constexpr int32_t kNumREVPHChannels = 16;
} // namespace hal
diff --git a/hal/src/main/native/athena/Power.cpp b/hal/src/main/native/athena/Power.cpp
index 2cf4d33..e911d5d 100644
--- a/hal/src/main/native/athena/Power.cpp
+++ b/hal/src/main/native/athena/Power.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/Power.h"
@@ -27,11 +24,9 @@
} // namespace hal
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializePower() {}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
@@ -108,4 +103,22 @@
power->readFaultCounts_OverCurrentFaultCount3V3(status));
}
+void HAL_SetBrownoutVoltage(double voltage, int32_t* status) {
+ initializePower(status);
+ if (voltage < 0) {
+ voltage = 0;
+ }
+ if (voltage > 50) {
+ voltage = 50;
+ }
+ power->writeBrownoutVoltage250mV(static_cast<unsigned char>(voltage * 4),
+ status);
+}
+
+double HAL_GetBrownoutVoltage(int32_t* status) {
+ initializePower(status);
+ auto brownout = power->readBrownoutVoltage250mV(status);
+ return brownout / 4.0;
+}
+
} // extern "C"
diff --git a/hal/src/main/native/athena/PowerDistribution.cpp b/hal/src/main/native/athena/PowerDistribution.cpp
new file mode 100644
index 0000000..f7fe88f
--- /dev/null
+++ b/hal/src/main/native/athena/PowerDistribution.cpp
@@ -0,0 +1,208 @@
+// 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/PowerDistribution.h"
+
+#include "CTREPDP.h"
+#include "HALInternal.h"
+#include "PortsInternal.h"
+#include "REVPDH.h"
+#include "hal/Errors.h"
+#include "hal/handles/HandlesInternal.h"
+
+using namespace hal;
+
+extern "C" {
+
+HAL_PowerDistributionHandle HAL_InitializePowerDistribution(
+ int32_t moduleNumber, HAL_PowerDistributionType type,
+ const char* allocationLocation, int32_t* status) {
+ if (type == HAL_PowerDistributionType::HAL_PowerDistributionType_kAutomatic) {
+ type = HAL_PowerDistributionType::HAL_PowerDistributionType_kCTRE;
+ }
+
+ if (type == HAL_PowerDistributionType::HAL_PowerDistributionType_kCTRE) {
+ if (moduleNumber == HAL_DEFAULT_POWER_DISTRIBUTION_MODULE) {
+ moduleNumber = 0;
+ }
+ return static_cast<HAL_PowerDistributionHandle>(
+ HAL_InitializePDP(moduleNumber, allocationLocation, status)); // TODO
+ } else {
+ if (moduleNumber == HAL_DEFAULT_POWER_DISTRIBUTION_MODULE) {
+ moduleNumber = 1;
+ }
+ return static_cast<HAL_PowerDistributionHandle>(
+ HAL_REV_InitializePDH(moduleNumber, allocationLocation, status));
+ }
+}
+
+#define IsCtre(handle) ::hal::isHandleType(handle, HAL_HandleEnum::CTREPDP)
+
+void HAL_CleanPowerDistribution(HAL_PowerDistributionHandle handle) {
+ if (IsCtre(handle)) {
+ HAL_CleanPDP(handle);
+ } else {
+ HAL_REV_FreePDH(handle);
+ }
+}
+
+int32_t HAL_GetPowerDistributionModuleNumber(HAL_PowerDistributionHandle handle,
+ int32_t* status) {
+ if (IsCtre(handle)) {
+ return HAL_GetPDPModuleNumber(handle, status);
+ } else {
+ return HAL_REV_GetPDHModuleNumber(handle, status);
+ }
+}
+
+HAL_Bool HAL_CheckPowerDistributionChannel(HAL_PowerDistributionHandle handle,
+ int32_t channel) {
+ if (IsCtre(handle)) {
+ return HAL_CheckPDPChannel(channel);
+ } else {
+ return HAL_REV_CheckPDHChannelNumber(channel);
+ }
+}
+
+HAL_Bool HAL_CheckPowerDistributionModule(int32_t module,
+ HAL_PowerDistributionType type) {
+ if (type == HAL_PowerDistributionType::HAL_PowerDistributionType_kCTRE) {
+ return HAL_CheckPDPModule(module);
+ } else {
+ return HAL_REV_CheckPDHModuleNumber(module);
+ }
+}
+
+HAL_PowerDistributionType HAL_GetPowerDistributionType(
+ HAL_PowerDistributionHandle handle, int32_t* status) {
+ return IsCtre(handle)
+ ? HAL_PowerDistributionType::HAL_PowerDistributionType_kCTRE
+ : HAL_PowerDistributionType::HAL_PowerDistributionType_kRev;
+}
+
+int32_t HAL_GetPowerDistributionNumChannels(HAL_PowerDistributionHandle handle,
+ int32_t* status) {
+ if (IsCtre(handle)) {
+ return kNumCTREPDPChannels;
+ } else {
+ return kNumREVPDHChannels;
+ }
+}
+
+double HAL_GetPowerDistributionTemperature(HAL_PowerDistributionHandle handle,
+ int32_t* status) {
+ if (IsCtre(handle)) {
+ return HAL_GetPDPTemperature(handle, status);
+ } else {
+ // Not supported
+ return 0;
+ }
+}
+
+double HAL_GetPowerDistributionVoltage(HAL_PowerDistributionHandle handle,
+ int32_t* status) {
+ if (IsCtre(handle)) {
+ return HAL_GetPDPVoltage(handle, status);
+ } else {
+ return HAL_REV_GetPDHSupplyVoltage(handle, status);
+ }
+}
+
+double HAL_GetPowerDistributionChannelCurrent(
+ HAL_PowerDistributionHandle handle, int32_t channel, int32_t* status) {
+ if (IsCtre(handle)) {
+ return HAL_GetPDPChannelCurrent(handle, channel, status);
+ } else {
+ return HAL_REV_GetPDHChannelCurrent(handle, channel, status);
+ }
+}
+
+void HAL_GetPowerDistributionAllChannelCurrents(
+ HAL_PowerDistributionHandle handle, double* currents,
+ int32_t currentsLength, int32_t* status) {
+ if (IsCtre(handle)) {
+ if (currentsLength < kNumCTREPDPChannels) {
+ *status = PARAMETER_OUT_OF_RANGE;
+ SetLastError(status, "Output array not large enough");
+ return;
+ }
+ return HAL_GetPDPAllChannelCurrents(handle, currents, status);
+ } else {
+ if (currentsLength < kNumREVPDHChannels) {
+ *status = PARAMETER_OUT_OF_RANGE;
+ SetLastError(status, "Output array not large enough");
+ return;
+ }
+ return HAL_REV_GetPDHAllChannelCurrents(handle, currents, status);
+ }
+}
+
+double HAL_GetPowerDistributionTotalCurrent(HAL_PowerDistributionHandle handle,
+ int32_t* status) {
+ if (IsCtre(handle)) {
+ return HAL_GetPDPTotalCurrent(handle, status);
+ } else {
+ return HAL_REV_GetPDHTotalCurrent(handle, status);
+ }
+}
+
+double HAL_GetPowerDistributionTotalPower(HAL_PowerDistributionHandle handle,
+ int32_t* status) {
+ if (IsCtre(handle)) {
+ return HAL_GetPDPTotalPower(handle, status);
+ } else {
+ // Not currently supported
+ return 0;
+ }
+}
+
+double HAL_GetPowerDistributionTotalEnergy(HAL_PowerDistributionHandle handle,
+ int32_t* status) {
+ if (IsCtre(handle)) {
+ return HAL_GetPDPTotalEnergy(handle, status);
+ } else {
+ // Not currently supported
+ return 0;
+ }
+}
+
+void HAL_ResetPowerDistributionTotalEnergy(HAL_PowerDistributionHandle handle,
+ int32_t* status) {
+ if (IsCtre(handle)) {
+ HAL_ResetPDPTotalEnergy(handle, status);
+ } else {
+ // Not supported
+ }
+}
+
+void HAL_ClearPowerDistributionStickyFaults(HAL_PowerDistributionHandle handle,
+ int32_t* status) {
+ if (IsCtre(handle)) {
+ HAL_ClearPDPStickyFaults(handle, status);
+ } else {
+ HAL_REV_ClearPDHFaults(handle, status);
+ }
+}
+
+void HAL_SetPowerDistributionSwitchableChannel(
+ HAL_PowerDistributionHandle handle, HAL_Bool enabled, int32_t* status) {
+ if (IsCtre(handle)) {
+ // No-op on CTRE
+ return;
+ } else {
+ HAL_REV_SetPDHSwitchableChannel(handle, enabled, status);
+ }
+}
+
+HAL_Bool HAL_GetPowerDistributionSwitchableChannel(
+ HAL_PowerDistributionHandle handle, int32_t* status) {
+ if (IsCtre(handle)) {
+ // No-op on CTRE
+ return false;
+ } else {
+ return HAL_REV_GetPDHSwitchableChannelState(handle, status);
+ }
+}
+
+} // extern "C"
diff --git a/hal/src/main/native/athena/REVPDH.cpp b/hal/src/main/native/athena/REVPDH.cpp
new file mode 100644
index 0000000..9ad45b5
--- /dev/null
+++ b/hal/src/main/native/athena/REVPDH.cpp
@@ -0,0 +1,798 @@
+// 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 "REVPDH.h"
+
+#include <hal/CANAPI.h>
+#include <hal/CANAPITypes.h>
+#include <hal/Errors.h>
+#include <hal/handles/HandlesInternal.h>
+#include <hal/handles/IndexedHandleResource.h>
+
+#include <cstring>
+
+#include <fmt/format.h>
+
+#include "HALInitializer.h"
+#include "HALInternal.h"
+#include "PortsInternal.h"
+#include "rev/PDHFrames.h"
+
+using namespace hal;
+
+static constexpr HAL_CANManufacturer manufacturer =
+ HAL_CANManufacturer::HAL_CAN_Man_kREV;
+
+static constexpr HAL_CANDeviceType deviceType =
+ HAL_CANDeviceType::HAL_CAN_Dev_kPowerDistribution;
+
+static constexpr int32_t kDefaultControlPeriod = 50;
+
+namespace {
+
+struct REV_PDHObj {
+ int32_t controlPeriod;
+ HAL_CANHandle hcan;
+ std::string previousAllocation;
+};
+
+} // namespace
+
+static constexpr uint32_t APIFromExtId(uint32_t extId) {
+ return (extId >> 6) & 0x3FF;
+}
+
+static constexpr uint32_t PDH_SWITCH_CHANNEL_SET_FRAME_API =
+ APIFromExtId(PDH_SWITCH_CHANNEL_SET_FRAME_ID);
+
+static constexpr uint32_t PDH_STATUS0_FRAME_API =
+ APIFromExtId(PDH_STATUS0_FRAME_ID);
+static constexpr uint32_t PDH_STATUS1_FRAME_API =
+ APIFromExtId(PDH_STATUS1_FRAME_ID);
+static constexpr uint32_t PDH_STATUS2_FRAME_API =
+ APIFromExtId(PDH_STATUS2_FRAME_ID);
+static constexpr uint32_t PDH_STATUS3_FRAME_API =
+ APIFromExtId(PDH_STATUS3_FRAME_ID);
+static constexpr uint32_t PDH_STATUS4_FRAME_API =
+ APIFromExtId(PDH_STATUS4_FRAME_ID);
+
+static constexpr uint32_t PDH_CLEAR_FAULTS_FRAME_API =
+ APIFromExtId(PDH_CLEAR_FAULTS_FRAME_ID);
+
+static constexpr uint32_t PDH_IDENTIFY_FRAME_API =
+ APIFromExtId(PDH_IDENTIFY_FRAME_ID);
+
+static constexpr uint32_t PDH_VERSION_FRAME_API =
+ APIFromExtId(PDH_VERSION_FRAME_ID);
+
+static constexpr uint32_t PDH_CONFIGURE_HR_CHANNEL_FRAME_API =
+ APIFromExtId(PDH_CONFIGURE_HR_CHANNEL_FRAME_ID);
+
+static constexpr int32_t kPDHFrameStatus0Timeout = 20;
+static constexpr int32_t kPDHFrameStatus1Timeout = 20;
+static constexpr int32_t kPDHFrameStatus2Timeout = 20;
+static constexpr int32_t kPDHFrameStatus3Timeout = 20;
+static constexpr int32_t kPDHFrameStatus4Timeout = 20;
+
+static IndexedHandleResource<HAL_REVPDHHandle, REV_PDHObj, kNumREVPDHModules,
+ HAL_HandleEnum::REVPDH>* REVPDHHandles;
+
+namespace hal::init {
+void InitializeREVPDH() {
+ static IndexedHandleResource<HAL_REVPDHHandle, REV_PDHObj, kNumREVPDHModules,
+ HAL_HandleEnum::REVPDH>
+ rH;
+ REVPDHHandles = &rH;
+}
+} // namespace hal::init
+
+extern "C" {
+
+static PDH_status0_t HAL_REV_ReadPDHStatus0(HAL_CANHandle hcan,
+ int32_t* status) {
+ uint8_t packedData[8] = {0};
+ int32_t length = 0;
+ uint64_t timestamp = 0;
+ PDH_status0_t result = {};
+
+ HAL_ReadCANPacketTimeout(hcan, PDH_STATUS0_FRAME_API, packedData, &length,
+ ×tamp, kPDHFrameStatus0Timeout * 2, status);
+
+ if (*status != 0) {
+ return result;
+ }
+
+ PDH_status0_unpack(&result, packedData, PDH_STATUS0_LENGTH);
+
+ return result;
+}
+
+static PDH_status1_t HAL_REV_ReadPDHStatus1(HAL_CANHandle hcan,
+ int32_t* status) {
+ uint8_t packedData[8] = {0};
+ int32_t length = 0;
+ uint64_t timestamp = 0;
+ PDH_status1_t result = {};
+
+ HAL_ReadCANPacketTimeout(hcan, PDH_STATUS1_FRAME_API, packedData, &length,
+ ×tamp, kPDHFrameStatus1Timeout * 2, status);
+
+ if (*status != 0) {
+ return result;
+ }
+
+ PDH_status1_unpack(&result, packedData, PDH_STATUS1_LENGTH);
+
+ return result;
+}
+
+static PDH_status2_t HAL_REV_ReadPDHStatus2(HAL_CANHandle hcan,
+ int32_t* status) {
+ uint8_t packedData[8] = {0};
+ int32_t length = 0;
+ uint64_t timestamp = 0;
+ PDH_status2_t result = {};
+
+ HAL_ReadCANPacketTimeout(hcan, PDH_STATUS2_FRAME_API, packedData, &length,
+ ×tamp, kPDHFrameStatus2Timeout * 2, status);
+
+ if (*status != 0) {
+ return result;
+ }
+
+ PDH_status2_unpack(&result, packedData, PDH_STATUS2_LENGTH);
+
+ return result;
+}
+
+static PDH_status3_t HAL_REV_ReadPDHStatus3(HAL_CANHandle hcan,
+ int32_t* status) {
+ uint8_t packedData[8] = {0};
+ int32_t length = 0;
+ uint64_t timestamp = 0;
+ PDH_status3_t result = {};
+
+ HAL_ReadCANPacketTimeout(hcan, PDH_STATUS3_FRAME_API, packedData, &length,
+ ×tamp, kPDHFrameStatus3Timeout * 2, status);
+
+ if (*status != 0) {
+ return result;
+ }
+
+ PDH_status3_unpack(&result, packedData, PDH_STATUS3_LENGTH);
+
+ return result;
+}
+
+static PDH_status4_t HAL_REV_ReadPDHStatus4(HAL_CANHandle hcan,
+ int32_t* status) {
+ uint8_t packedData[8] = {0};
+ int32_t length = 0;
+ uint64_t timestamp = 0;
+ PDH_status4_t result = {};
+
+ HAL_ReadCANPacketTimeout(hcan, PDH_STATUS4_FRAME_API, packedData, &length,
+ ×tamp, kPDHFrameStatus4Timeout * 2, status);
+
+ if (*status != 0) {
+ return result;
+ }
+
+ PDH_status4_unpack(&result, packedData, PDH_STATUS4_LENGTH);
+
+ return result;
+}
+
+/**
+ * Helper function for the individual getter functions for status 4
+ */
+PDH_status4_t HAL_REV_GetPDHStatus4(HAL_REVPDHHandle handle, int32_t* status) {
+ PDH_status4_t statusFrame = {};
+ auto hpdh = REVPDHHandles->Get(handle);
+ if (hpdh == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return statusFrame;
+ }
+
+ statusFrame = HAL_REV_ReadPDHStatus4(hpdh->hcan, status);
+ return statusFrame;
+}
+
+HAL_REVPDHHandle HAL_REV_InitializePDH(int32_t module,
+ const char* allocationLocation,
+ int32_t* status) {
+ hal::init::CheckInit();
+ if (!HAL_REV_CheckPDHModuleNumber(module)) {
+ *status = RESOURCE_OUT_OF_RANGE;
+ return HAL_kInvalidHandle;
+ }
+
+ HAL_REVPDHHandle handle;
+ auto hpdh = REVPDHHandles->Allocate(module, &handle, status);
+ if (*status != 0) {
+ if (hpdh) {
+ hal::SetLastErrorPreviouslyAllocated(status, "REV PDH", module,
+ hpdh->previousAllocation);
+ } else {
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PDH", 0,
+ kNumREVPDHModules, module);
+ }
+ return HAL_kInvalidHandle; // failed to allocate. Pass error back.
+ }
+
+ HAL_CANHandle hcan =
+ HAL_InitializeCAN(manufacturer, module, deviceType, status);
+
+ if (*status != 0) {
+ REVPDHHandles->Free(handle);
+ return HAL_kInvalidHandle;
+ }
+
+ hpdh->previousAllocation = allocationLocation ? allocationLocation : "";
+ hpdh->hcan = hcan;
+ hpdh->controlPeriod = kDefaultControlPeriod;
+
+ return handle;
+}
+
+void HAL_REV_FreePDH(HAL_REVPDHHandle handle) {
+ auto hpdh = REVPDHHandles->Get(handle);
+ if (hpdh == nullptr) {
+ return;
+ }
+
+ HAL_CleanCAN(hpdh->hcan);
+
+ REVPDHHandles->Free(handle);
+}
+
+int32_t HAL_REV_GetPDHModuleNumber(HAL_REVPDHHandle handle, int32_t* status) {
+ return hal::getHandleIndex(handle);
+}
+
+HAL_Bool HAL_REV_CheckPDHModuleNumber(int32_t module) {
+ return ((module >= 1) && (module < kNumREVPDHModules)) ? 1 : 0;
+}
+
+HAL_Bool HAL_REV_CheckPDHChannelNumber(int32_t channel) {
+ return ((channel >= 0) && (channel < kNumREVPDHChannels)) ? 1 : 0;
+}
+
+double HAL_REV_GetPDHChannelCurrent(HAL_REVPDHHandle handle, int32_t channel,
+ int32_t* status) {
+ auto hpdh = REVPDHHandles->Get(handle);
+ if (hpdh == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return 0;
+ }
+
+ if (!HAL_REV_CheckPDHChannelNumber(channel)) {
+ *status = RESOURCE_OUT_OF_RANGE;
+ return 0;
+ }
+
+ // Determine what periodic status the channel is in
+ if (channel < 6) {
+ // Periodic status 0
+ PDH_status0_t statusFrame = HAL_REV_ReadPDHStatus0(hpdh->hcan, status);
+ switch (channel) {
+ case 0:
+ return PDH_status0_channel_0_current_decode(
+ statusFrame.channel_0_current);
+ case 1:
+ return PDH_status0_channel_1_current_decode(
+ statusFrame.channel_1_current);
+ case 2:
+ return PDH_status0_channel_2_current_decode(
+ statusFrame.channel_2_current);
+ case 3:
+ return PDH_status0_channel_3_current_decode(
+ statusFrame.channel_3_current);
+ case 4:
+ return PDH_status0_channel_4_current_decode(
+ statusFrame.channel_4_current);
+ case 5:
+ return PDH_status0_channel_5_current_decode(
+ statusFrame.channel_5_current);
+ }
+ } else if (channel < 12) {
+ // Periodic status 1
+ PDH_status1_t statusFrame = HAL_REV_ReadPDHStatus1(hpdh->hcan, status);
+ switch (channel) {
+ case 6:
+ return PDH_status1_channel_6_current_decode(
+ statusFrame.channel_6_current);
+ case 7:
+ return PDH_status1_channel_7_current_decode(
+ statusFrame.channel_7_current);
+ case 8:
+ return PDH_status1_channel_8_current_decode(
+ statusFrame.channel_8_current);
+ case 9:
+ return PDH_status1_channel_9_current_decode(
+ statusFrame.channel_9_current);
+ case 10:
+ return PDH_status1_channel_10_current_decode(
+ statusFrame.channel_10_current);
+ case 11:
+ return PDH_status1_channel_11_current_decode(
+ statusFrame.channel_11_current);
+ }
+ } else if (channel < 18) {
+ // Periodic status 2
+ PDH_status2_t statusFrame = HAL_REV_ReadPDHStatus2(hpdh->hcan, status);
+ switch (channel) {
+ case 12:
+ return PDH_status2_channel_12_current_decode(
+ statusFrame.channel_12_current);
+ case 13:
+ return PDH_status2_channel_13_current_decode(
+ statusFrame.channel_13_current);
+ case 14:
+ return PDH_status2_channel_14_current_decode(
+ statusFrame.channel_14_current);
+ case 15:
+ return PDH_status2_channel_15_current_decode(
+ statusFrame.channel_15_current);
+ case 16:
+ return PDH_status2_channel_16_current_decode(
+ statusFrame.channel_16_current);
+ case 17:
+ return PDH_status2_channel_17_current_decode(
+ statusFrame.channel_17_current);
+ }
+ } else if (channel < 24) {
+ // Periodic status 3
+ PDH_status3_t statusFrame = HAL_REV_ReadPDHStatus3(hpdh->hcan, status);
+ switch (channel) {
+ case 18:
+ return PDH_status3_channel_18_current_decode(
+ statusFrame.channel_18_current);
+ case 19:
+ return PDH_status3_channel_19_current_decode(
+ statusFrame.channel_19_current);
+ case 20:
+ return PDH_status3_channel_20_current_decode(
+ statusFrame.channel_20_current);
+ case 21:
+ return PDH_status3_channel_21_current_decode(
+ statusFrame.channel_21_current);
+ case 22:
+ return PDH_status3_channel_22_current_decode(
+ statusFrame.channel_22_current);
+ case 23:
+ return PDH_status3_channel_23_current_decode(
+ statusFrame.channel_23_current);
+ }
+ }
+ return 0;
+}
+
+void HAL_REV_GetPDHAllChannelCurrents(HAL_REVPDHHandle handle, double* currents,
+ int32_t* status) {
+ auto hpdh = REVPDHHandles->Get(handle);
+ if (hpdh == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
+ PDH_status0_t statusFrame0 = HAL_REV_ReadPDHStatus0(hpdh->hcan, status);
+ PDH_status1_t statusFrame1 = HAL_REV_ReadPDHStatus1(hpdh->hcan, status);
+ PDH_status2_t statusFrame2 = HAL_REV_ReadPDHStatus2(hpdh->hcan, status);
+ PDH_status3_t statusFrame3 = HAL_REV_ReadPDHStatus3(hpdh->hcan, status);
+
+ currents[0] =
+ PDH_status0_channel_0_current_decode(statusFrame0.channel_0_current);
+ currents[1] =
+ PDH_status0_channel_1_current_decode(statusFrame0.channel_1_current);
+ currents[2] =
+ PDH_status0_channel_2_current_decode(statusFrame0.channel_2_current);
+ currents[3] =
+ PDH_status0_channel_3_current_decode(statusFrame0.channel_3_current);
+ currents[4] =
+ PDH_status0_channel_4_current_decode(statusFrame0.channel_4_current);
+ currents[5] =
+ PDH_status0_channel_5_current_decode(statusFrame0.channel_5_current);
+ currents[6] =
+ PDH_status1_channel_6_current_decode(statusFrame1.channel_6_current);
+ currents[7] =
+ PDH_status1_channel_7_current_decode(statusFrame1.channel_7_current);
+ currents[8] =
+ PDH_status1_channel_8_current_decode(statusFrame1.channel_8_current);
+ currents[9] =
+ PDH_status1_channel_9_current_decode(statusFrame1.channel_9_current);
+ currents[10] =
+ PDH_status1_channel_10_current_decode(statusFrame1.channel_10_current);
+ currents[11] =
+ PDH_status1_channel_11_current_decode(statusFrame1.channel_11_current);
+ currents[12] =
+ PDH_status2_channel_12_current_decode(statusFrame2.channel_12_current);
+ currents[13] =
+ PDH_status2_channel_13_current_decode(statusFrame2.channel_13_current);
+ currents[14] =
+ PDH_status2_channel_14_current_decode(statusFrame2.channel_14_current);
+ currents[15] =
+ PDH_status2_channel_15_current_decode(statusFrame2.channel_15_current);
+ currents[16] =
+ PDH_status2_channel_16_current_decode(statusFrame2.channel_16_current);
+ currents[17] =
+ PDH_status2_channel_17_current_decode(statusFrame2.channel_17_current);
+ currents[18] =
+ PDH_status3_channel_18_current_decode(statusFrame3.channel_18_current);
+ currents[19] =
+ PDH_status3_channel_19_current_decode(statusFrame3.channel_19_current);
+ currents[20] =
+ PDH_status3_channel_20_current_decode(statusFrame3.channel_20_current);
+ currents[21] =
+ PDH_status3_channel_21_current_decode(statusFrame3.channel_21_current);
+ currents[22] =
+ PDH_status3_channel_22_current_decode(statusFrame3.channel_22_current);
+ currents[23] =
+ PDH_status3_channel_23_current_decode(statusFrame3.channel_23_current);
+}
+
+uint16_t HAL_REV_GetPDHTotalCurrent(HAL_REVPDHHandle handle, int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return 0;
+ }
+
+ return PDH_status4_total_current_decode(statusFrame.total_current);
+}
+
+void HAL_REV_SetPDHSwitchableChannel(HAL_REVPDHHandle handle, HAL_Bool enabled,
+ int32_t* status) {
+ auto hpdh = REVPDHHandles->Get(handle);
+ if (hpdh == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
+ uint8_t packedData[8] = {0};
+ PDH_switch_channel_set_t frame;
+ frame.output_set_value = enabled;
+ frame.use_system_enable = false;
+ PDH_switch_channel_set_pack(packedData, &frame, 1);
+
+ HAL_WriteCANPacket(hpdh->hcan, packedData, PDH_SWITCH_CHANNEL_SET_LENGTH,
+ PDH_SWITCH_CHANNEL_SET_FRAME_API, status);
+}
+
+HAL_Bool HAL_REV_GetPDHSwitchableChannelState(HAL_REVPDHHandle handle,
+ int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return 0.0;
+ }
+
+ return PDH_status4_sw_state_decode(statusFrame.sw_state);
+}
+
+HAL_Bool HAL_REV_CheckPDHChannelBrownout(HAL_REVPDHHandle handle,
+ int32_t channel, int32_t* status) {
+ auto hpdh = REVPDHHandles->Get(handle);
+ if (hpdh == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return 0;
+ }
+
+ if (!HAL_REV_CheckPDHChannelNumber(channel)) {
+ *status = RESOURCE_OUT_OF_RANGE;
+ return 0;
+ }
+
+ // Determine what periodic status the channel is in
+ if (channel < 4) {
+ // Periodic status 0
+ PDH_status0_t statusFrame = HAL_REV_ReadPDHStatus0(hpdh->hcan, status);
+ switch (channel) {
+ case 0:
+ return PDH_status0_channel_0_brownout_decode(
+ statusFrame.channel_0_brownout);
+ case 1:
+ return PDH_status0_channel_1_brownout_decode(
+ statusFrame.channel_1_brownout);
+ case 2:
+ return PDH_status0_channel_2_brownout_decode(
+ statusFrame.channel_2_brownout);
+ case 3:
+ return PDH_status0_channel_3_brownout_decode(
+ statusFrame.channel_3_brownout);
+ }
+ } else if (channel < 8) {
+ // Periodic status 1
+ PDH_status1_t statusFrame = HAL_REV_ReadPDHStatus1(hpdh->hcan, status);
+ switch (channel) {
+ case 4:
+ return PDH_status1_channel_4_brownout_decode(
+ statusFrame.channel_4_brownout);
+ case 5:
+ return PDH_status1_channel_5_brownout_decode(
+ statusFrame.channel_5_brownout);
+ case 6:
+ return PDH_status1_channel_6_brownout_decode(
+ statusFrame.channel_6_brownout);
+ case 7:
+ return PDH_status1_channel_7_brownout_decode(
+ statusFrame.channel_7_brownout);
+ }
+ } else if (channel < 12) {
+ // Periodic status 2
+ PDH_status2_t statusFrame = HAL_REV_ReadPDHStatus2(hpdh->hcan, status);
+ switch (channel) {
+ case 8:
+ return PDH_status2_channel_8_brownout_decode(
+ statusFrame.channel_8_brownout);
+ case 9:
+ return PDH_status2_channel_9_brownout_decode(
+ statusFrame.channel_9_brownout);
+ case 10:
+ return PDH_status2_channel_10_brownout_decode(
+ statusFrame.channel_10_brownout);
+ case 11:
+ return PDH_status2_channel_11_brownout_decode(
+ statusFrame.channel_11_brownout);
+ }
+ } else if (channel < 24) {
+ // Periodic status 3
+ PDH_status3_t statusFrame = HAL_REV_ReadPDHStatus3(hpdh->hcan, status);
+ switch (channel) {
+ case 12:
+ return PDH_status3_channel_12_brownout_decode(
+ statusFrame.channel_12_brownout);
+ case 13:
+ return PDH_status3_channel_13_brownout_decode(
+ statusFrame.channel_13_brownout);
+ case 14:
+ return PDH_status3_channel_14_brownout_decode(
+ statusFrame.channel_14_brownout);
+ case 15:
+ return PDH_status3_channel_15_brownout_decode(
+ statusFrame.channel_15_brownout);
+ case 16:
+ return PDH_status3_channel_16_brownout_decode(
+ statusFrame.channel_16_brownout);
+ case 17:
+ return PDH_status3_channel_17_brownout_decode(
+ statusFrame.channel_17_brownout);
+ case 18:
+ return PDH_status3_channel_18_brownout_decode(
+ statusFrame.channel_18_brownout);
+ case 19:
+ return PDH_status3_channel_19_brownout_decode(
+ statusFrame.channel_19_brownout);
+ case 20:
+ return PDH_status3_channel_20_brownout_decode(
+ statusFrame.channel_20_brownout);
+ case 21:
+ return PDH_status3_channel_21_brownout_decode(
+ statusFrame.channel_21_brownout);
+ case 22:
+ return PDH_status3_channel_22_brownout_decode(
+ statusFrame.channel_22_brownout);
+ case 23:
+ return PDH_status3_channel_23_brownout_decode(
+ statusFrame.channel_23_brownout);
+ }
+ }
+ return 0;
+}
+
+double HAL_REV_GetPDHSupplyVoltage(HAL_REVPDHHandle handle, int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return 0.0;
+ }
+
+ return PDH_status4_v_bus_decode(statusFrame.v_bus);
+}
+
+HAL_Bool HAL_REV_IsPDHEnabled(HAL_REVPDHHandle handle, int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return false;
+ }
+
+ return PDH_status4_system_enable_decode(statusFrame.system_enable);
+}
+
+HAL_Bool HAL_REV_CheckPDHBrownout(HAL_REVPDHHandle handle, int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return false;
+ }
+
+ return PDH_status4_brownout_decode(statusFrame.brownout);
+}
+
+HAL_Bool HAL_REV_CheckPDHCANWarning(HAL_REVPDHHandle handle, int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return 0.0;
+ }
+
+ return PDH_status4_can_warning_decode(statusFrame.can_warning);
+}
+
+HAL_Bool HAL_REV_CheckPDHHardwareFault(HAL_REVPDHHandle handle,
+ int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return 0.0;
+ }
+
+ return PDH_status4_hardware_fault_decode(statusFrame.hardware_fault);
+}
+
+HAL_Bool HAL_REV_CheckPDHStickyBrownout(HAL_REVPDHHandle handle,
+ int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return 0.0;
+ }
+
+ return PDH_status4_sticky_brownout_decode(statusFrame.sticky_brownout);
+}
+
+HAL_Bool HAL_REV_CheckPDHStickyCANWarning(HAL_REVPDHHandle handle,
+ int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return 0.0;
+ }
+
+ return PDH_status4_sticky_can_warning_decode(statusFrame.sticky_can_warning);
+}
+
+HAL_Bool HAL_REV_CheckPDHStickyCANBusOff(HAL_REVPDHHandle handle,
+ int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return 0.0;
+ }
+
+ return PDH_status4_sticky_can_bus_off_decode(statusFrame.sticky_can_bus_off);
+}
+
+HAL_Bool HAL_REV_CheckPDHStickyHardwareFault(HAL_REVPDHHandle handle,
+ int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return 0.0;
+ }
+
+ return PDH_status4_sticky_hardware_fault_decode(
+ statusFrame.sticky_hardware_fault);
+}
+
+HAL_Bool HAL_REV_CheckPDHStickyFirmwareFault(HAL_REVPDHHandle handle,
+ int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return 0.0;
+ }
+
+ return PDH_status4_sticky_firmware_fault_decode(
+ statusFrame.sticky_firmware_fault);
+}
+
+HAL_Bool HAL_REV_CheckPDHStickyChannelBrownout(HAL_REVPDHHandle handle,
+ int32_t channel,
+ int32_t* status) {
+ if (channel < 20 || channel > 23) {
+ *status = RESOURCE_OUT_OF_RANGE;
+ return 0.0;
+ }
+
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return 0.0;
+ }
+
+ switch (channel) {
+ case 20:
+ return PDH_status4_sticky_ch20_brownout_decode(
+ statusFrame.sticky_ch20_brownout);
+ case 21:
+ return PDH_status4_sticky_ch21_brownout_decode(
+ statusFrame.sticky_ch21_brownout);
+ case 22:
+ return PDH_status4_sticky_ch22_brownout_decode(
+ statusFrame.sticky_ch22_brownout);
+ case 23:
+ return PDH_status4_sticky_ch23_brownout_decode(
+ statusFrame.sticky_ch23_brownout);
+ }
+ return 0;
+}
+
+HAL_Bool HAL_REV_CheckPDHStickyHasReset(HAL_REVPDHHandle handle,
+ int32_t* status) {
+ PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
+
+ if (*status != 0) {
+ return 0.0;
+ }
+
+ return PDH_status4_sticky_has_reset_decode(statusFrame.sticky_has_reset);
+}
+
+REV_PDH_Version HAL_REV_GetPDHVersion(HAL_REVPDHHandle handle,
+ int32_t* status) {
+ REV_PDH_Version version;
+ std::memset(&version, 0, sizeof(version));
+ uint8_t packedData[8] = {0};
+ int32_t length = 0;
+ uint64_t timestamp = 0;
+ PDH_version_t result = {};
+ auto hpdh = REVPDHHandles->Get(handle);
+ if (hpdh == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return version;
+ }
+
+ HAL_WriteCANRTRFrame(hpdh->hcan, PDH_VERSION_LENGTH, PDH_VERSION_FRAME_API,
+ status);
+
+ if (*status != 0) {
+ return version;
+ }
+
+ HAL_ReadCANPacketTimeout(hpdh->hcan, PDH_VERSION_FRAME_API, packedData,
+ &length, ×tamp, kDefaultControlPeriod * 2,
+ status);
+
+ if (*status != 0) {
+ return version;
+ }
+
+ PDH_version_unpack(&result, packedData, PDH_VERSION_LENGTH);
+
+ version.firmwareMajor = result.firmware_year;
+ version.firmwareMinor = result.firmware_minor;
+ version.firmwareFix = result.firmware_fix;
+ version.hardwareRev = result.hardware_code;
+ version.uniqueId = result.unique_id;
+
+ return version;
+}
+
+void HAL_REV_ClearPDHFaults(HAL_REVPDHHandle handle, int32_t* status) {
+ auto hpdh = REVPDHHandles->Get(handle);
+ if (hpdh == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
+ uint8_t packedData[8] = {0};
+ HAL_WriteCANPacket(hpdh->hcan, packedData, PDH_CLEAR_FAULTS_LENGTH,
+ PDH_CLEAR_FAULTS_FRAME_API, status);
+}
+
+void HAL_REV_IdentifyPDH(HAL_REVPDHHandle handle, int32_t* status) {
+ auto hpdh = REVPDHHandles->Get(handle);
+ if (hpdh == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
+ uint8_t packedData[8] = {0};
+ HAL_WriteCANPacket(hpdh->hcan, packedData, PDH_IDENTIFY_LENGTH,
+ PDH_IDENTIFY_FRAME_API, status);
+}
+
+} // extern "C"
diff --git a/hal/src/main/native/athena/REVPDH.h b/hal/src/main/native/athena/REVPDH.h
new file mode 100644
index 0000000..228d05c
--- /dev/null
+++ b/hal/src/main/native/athena/REVPDH.h
@@ -0,0 +1,314 @@
+// 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>
+
+#include "hal/Types.h"
+
+/**
+ * @defgroup hal_rev_pdh REV Power Distribution Hub API Functions
+ * @ingroup hal_capi
+ * @{
+ */
+
+struct REV_PDH_Version {
+ uint32_t firmwareMajor;
+ uint32_t firmwareMinor;
+ uint32_t firmwareFix;
+ uint32_t hardwareRev;
+ uint32_t uniqueId;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initializes a REV Power Distribution Hub (PDH) device.
+ *
+ * @param module the device CAN ID (1 .. 63)
+ * @return the created PDH handle
+ */
+HAL_REVPDHHandle HAL_REV_InitializePDH(int32_t module,
+ const char* allocationLocation,
+ int32_t* status);
+
+/**
+ * Frees a PDH device handle.
+ *
+ * @param handle the previously created PDH handle
+ */
+void HAL_REV_FreePDH(HAL_REVPDHHandle handle);
+
+/**
+ * Gets the module number for a pdh.
+ */
+int32_t HAL_REV_GetPDHModuleNumber(HAL_REVPDHHandle handle, int32_t* status);
+
+/**
+ * Checks if a PDH module number is valid.
+ *
+ * Does not check if a PDH device with this module has been initialized.
+ *
+ * @param module module number (1 .. 63)
+ * @return 1 if the module number is valid; 0 otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHModuleNumber(int32_t module);
+
+/**
+ * Checks if a PDH channel number is valid.
+ *
+ * @param module channel number (0 .. HAL_REV_PDH_NUM_CHANNELS)
+ * @return 1 if the channel number is valid; 0 otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHChannelNumber(int32_t channel);
+
+/**
+ * Gets the current of a PDH channel in Amps.
+ *
+ * @param handle PDH handle
+ * @param channel the channel to retrieve the current of (0 ..
+ * HAL_REV_PDH_NUM_CHANNELS)
+ *
+ * @return the current of the PDH channel in Amps
+ */
+double HAL_REV_GetPDHChannelCurrent(HAL_REVPDHHandle handle, int32_t channel,
+ int32_t* status);
+
+/**
+ * @param handle PDH handle
+ * @param currents array of currents
+ */
+void HAL_REV_GetPDHAllChannelCurrents(HAL_REVPDHHandle handle, double* currents,
+ int32_t* status);
+
+/**
+ * Gets the total current of the PDH in Amps, measured to the nearest even
+ * integer.
+ *
+ * @param handle PDH handle
+ *
+ * @return the total current of the PDH in Amps
+ */
+uint16_t HAL_REV_GetPDHTotalCurrent(HAL_REVPDHHandle handle, int32_t* status);
+
+/**
+ * Sets the state of the switchable channel on a PDH device.
+ *
+ * @param handle PDH handle
+ * @param enabled 1 if the switchable channel should be enabled; 0
+ * otherwise
+ */
+void HAL_REV_SetPDHSwitchableChannel(HAL_REVPDHHandle handle, HAL_Bool enabled,
+ int32_t* status);
+
+/**
+ * Gets the current state of the switchable channel on a PDH device.
+ *
+ * This call relies on a periodic status sent by the PDH device and will be as
+ * fresh as the last packet received.
+ *
+ * @param handle PDH handle
+ * @return 1 if the switchable channel is enabled; 0 otherwise
+ */
+HAL_Bool HAL_REV_GetPDHSwitchableChannelState(HAL_REVPDHHandle handle,
+ int32_t* status);
+
+/**
+ * Checks if a PDH channel is currently experiencing a brownout condition.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ * @param channel the channel to retrieve the brownout status of
+ *
+ * @return 1 if the channel is experiencing a brownout; 0 otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHChannelBrownout(HAL_REVPDHHandle handle,
+ int32_t channel, int32_t* status);
+
+/**
+ * Gets the voltage being supplied to a PDH device.
+ *
+ * @param handle PDH handle
+ *
+ * @return the voltage at the input of the PDH in Volts
+ */
+double HAL_REV_GetPDHSupplyVoltage(HAL_REVPDHHandle handle, int32_t* status);
+
+/**
+ * Checks if a PDH device is currently enabled.
+ *
+ * @param handle PDH handle
+ *
+ * @return 1 if the PDH is enabled; 0 otherwise
+ */
+HAL_Bool HAL_REV_IsPDHEnabled(HAL_REVPDHHandle handle, int32_t* status);
+
+/**
+ * Checks if the input voltage on a PDH device is currently below the minimum
+ * voltage.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ *
+ * @return 1 if the PDH is experiencing a brownout; 0 otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHBrownout(HAL_REVPDHHandle handle, int32_t* status);
+
+/**
+ * Checks if the CAN RX or TX error levels on a PDH device have exceeded the
+ * warning threshold.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ *
+ * @return 1 if the device has exceeded the warning threshold; 0
+ * otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHCANWarning(HAL_REVPDHHandle handle, int32_t* status);
+
+/**
+ * Checks if a PDH device is currently malfunctioning.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ *
+ * @return 1 if the device is in a hardware fault state; 0
+ * otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHHardwareFault(HAL_REVPDHHandle handle,
+ int32_t* status);
+
+/**
+ * Checks if the input voltage on a PDH device has gone below the specified
+ * minimum voltage.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ *
+ * @return 1 if the device has had a brownout; 0 otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHStickyBrownout(HAL_REVPDHHandle handle,
+ int32_t* status);
+
+/**
+ * Checks if the CAN RX or TX error levels on a PDH device have exceeded the
+ * warning threshold.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ *
+ * @return 1 if the device has exceeded the CAN warning threshold;
+ * 0 otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHStickyCANWarning(HAL_REVPDHHandle handle,
+ int32_t* status);
+
+/**
+ * Checks if the CAN bus on a PDH device has previously experienced a 'Bus Off'
+ * event.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ *
+ * @return 1 if the device has experienced a 'Bus Off' event; 0
+ * otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHStickyCANBusOff(HAL_REVPDHHandle handle,
+ int32_t* status);
+
+/**
+ * Checks if a PDH device has malfunctioned.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ *
+ * @return 1 if the device has had a malfunction; 0 otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHStickyHardwareFault(HAL_REVPDHHandle handle,
+ int32_t* status);
+
+/**
+ * Checks if the firmware on a PDH device has malfunctioned and reset during
+ * operation.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ *
+ * @return 1 if the device has had a malfunction and reset; 0
+ * otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHStickyFirmwareFault(HAL_REVPDHHandle handle,
+ int32_t* status);
+
+/**
+ * Checks if a brownout has happened on channels 20-23 of a PDH device while it
+ * was enabled.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ * @param channel PDH channel to retrieve sticky brownout status (20 ..
+ * 23)
+ *
+ *
+ * @return 1 if the channel has had a brownout; 0 otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHStickyChannelBrownout(HAL_REVPDHHandle handle,
+ int32_t channel,
+ int32_t* status);
+
+/**
+ * Checks if a PDH device has reset.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ *
+ * @return 1 if the device has reset; 0 otherwise
+ */
+HAL_Bool HAL_REV_CheckPDHStickyHasReset(HAL_REVPDHHandle handle,
+ int32_t* status);
+
+/**
+ * Gets the firmware and hardware versions of a PDH device.
+ *
+ * @param handle PDH handle
+ *
+ * @return version information
+ */
+REV_PDH_Version HAL_REV_GetPDHVersion(HAL_REVPDHHandle handle, int32_t* status);
+
+/**
+ * Clears the sticky faults on a PDH device.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ */
+void HAL_REV_ClearPDHFaults(HAL_REVPDHHandle handle, int32_t* status);
+
+/**
+ * Identifies a PDH device by blinking its LED.
+ *
+ * NOTE: Not implemented in firmware as of 2021-04-23.
+ *
+ * @param handle PDH handle
+ */
+void HAL_REV_IdentifyPDH(HAL_REVPDHHandle handle, int32_t* status);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/hal/src/main/native/athena/REVPH.cpp b/hal/src/main/native/athena/REVPH.cpp
new file mode 100644
index 0000000..155f92c
--- /dev/null
+++ b/hal/src/main/native/athena/REVPH.cpp
@@ -0,0 +1,480 @@
+// 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/REVPH.h"
+
+#include <fmt/format.h>
+
+#include "HALInitializer.h"
+#include "HALInternal.h"
+#include "PortsInternal.h"
+#include "hal/CANAPI.h"
+#include "hal/Errors.h"
+#include "hal/handles/IndexedHandleResource.h"
+#include "rev/PHFrames.h"
+
+using namespace hal;
+
+static constexpr HAL_CANManufacturer manufacturer =
+ HAL_CANManufacturer::HAL_CAN_Man_kREV;
+
+static constexpr HAL_CANDeviceType deviceType =
+ HAL_CANDeviceType::HAL_CAN_Dev_kPneumatics;
+
+static constexpr int32_t kDefaultControlPeriod = 20;
+// static constexpr uint8_t kDefaultSensorMask = (1 <<
+// HAL_REV_PHSENSOR_DIGITAL);
+static constexpr uint8_t kDefaultCompressorDuty = 255;
+static constexpr uint8_t kDefaultPressureTarget = 120;
+static constexpr uint8_t kDefaultPressureHysteresis = 60;
+
+#define HAL_REV_MAX_PULSE_TIME 65534
+#define HAL_REV_MAX_PRESSURE_TARGET 120
+#define HAL_REV_MAX_PRESSURE_HYSTERESIS HAL_REV_MAX_PRESSURE_TARGET
+
+static constexpr uint32_t APIFromExtId(uint32_t extId) {
+ return (extId >> 6) & 0x3FF;
+}
+
+static constexpr uint32_t PH_SET_ALL_FRAME_API =
+ APIFromExtId(PH_SET_ALL_FRAME_ID);
+static constexpr uint32_t PH_PULSE_ONCE_FRAME_API =
+ APIFromExtId(PH_PULSE_ONCE_FRAME_ID);
+static constexpr uint32_t PH_STATUS0_FRAME_API =
+ APIFromExtId(PH_STATUS0_FRAME_ID);
+static constexpr uint32_t PH_STATUS1_FRAME_API =
+ APIFromExtId(PH_STATUS1_FRAME_ID);
+
+static constexpr int32_t kPHFrameStatus0Timeout = 50;
+static constexpr int32_t kPHFrameStatus1Timeout = 50;
+
+namespace {
+
+struct REV_PHObj {
+ int32_t controlPeriod;
+ PH_set_all_t desiredSolenoidsState;
+ wpi::mutex solenoidLock;
+ HAL_CANHandle hcan;
+ std::string previousAllocation;
+};
+
+} // namespace
+
+static IndexedHandleResource<HAL_REVPHHandle, REV_PHObj, 63,
+ HAL_HandleEnum::REVPH>* REVPHHandles;
+
+namespace hal::init {
+void InitializeREVPH() {
+ static IndexedHandleResource<HAL_REVPHHandle, REV_PHObj, kNumREVPHModules,
+ HAL_HandleEnum::REVPH>
+ rH;
+ REVPHHandles = &rH;
+}
+} // namespace hal::init
+
+static PH_status0_t HAL_REV_ReadPHStatus0(HAL_CANHandle hcan, int32_t* status) {
+ uint8_t packedData[8] = {0};
+ int32_t length = 0;
+ uint64_t timestamp = 0;
+ PH_status0_t result = {};
+
+ HAL_ReadCANPacketTimeout(hcan, PH_STATUS0_FRAME_API, packedData, &length,
+ ×tamp, kPHFrameStatus0Timeout * 2, status);
+
+ if (*status != 0) {
+ return result;
+ }
+
+ PH_status0_unpack(&result, packedData, PH_STATUS0_LENGTH);
+
+ return result;
+}
+
+static PH_status1_t HAL_REV_ReadPHStatus1(HAL_CANHandle hcan, int32_t* status) {
+ uint8_t packedData[8] = {0};
+ int32_t length = 0;
+ uint64_t timestamp = 0;
+ PH_status1_t result = {};
+
+ HAL_ReadCANPacketTimeout(hcan, PH_STATUS1_FRAME_API, packedData, &length,
+ ×tamp, kPHFrameStatus1Timeout * 2, status);
+
+ if (*status != 0) {
+ return result;
+ }
+
+ PH_status1_unpack(&result, packedData, PH_STATUS1_LENGTH);
+
+ return result;
+}
+
+enum REV_SolenoidState {
+ kSolenoidDisabled = 0,
+ kSolenoidEnabled,
+ kSolenoidControlledViaPulse
+};
+
+static void HAL_REV_UpdateDesiredPHSolenoidState(REV_PHObj* hph,
+ int32_t solenoid,
+ REV_SolenoidState state) {
+ switch (solenoid) {
+ case 0:
+ hph->desiredSolenoidsState.channel_0 = state;
+ break;
+ case 1:
+ hph->desiredSolenoidsState.channel_1 = state;
+ break;
+ case 2:
+ hph->desiredSolenoidsState.channel_2 = state;
+ break;
+ case 3:
+ hph->desiredSolenoidsState.channel_3 = state;
+ break;
+ case 4:
+ hph->desiredSolenoidsState.channel_4 = state;
+ break;
+ case 5:
+ hph->desiredSolenoidsState.channel_5 = state;
+ break;
+ case 6:
+ hph->desiredSolenoidsState.channel_6 = state;
+ break;
+ case 7:
+ hph->desiredSolenoidsState.channel_7 = state;
+ break;
+ case 8:
+ hph->desiredSolenoidsState.channel_8 = state;
+ break;
+ case 9:
+ hph->desiredSolenoidsState.channel_9 = state;
+ break;
+ case 10:
+ hph->desiredSolenoidsState.channel_10 = state;
+ break;
+ case 11:
+ hph->desiredSolenoidsState.channel_11 = state;
+ break;
+ case 12:
+ hph->desiredSolenoidsState.channel_12 = state;
+ break;
+ case 13:
+ hph->desiredSolenoidsState.channel_13 = state;
+ break;
+ case 14:
+ hph->desiredSolenoidsState.channel_14 = state;
+ break;
+ case 15:
+ hph->desiredSolenoidsState.channel_15 = state;
+ break;
+ }
+}
+
+static void HAL_REV_SendSolenoidsState(REV_PHObj* hph, int32_t* status) {
+ uint8_t packedData[PH_SET_ALL_LENGTH] = {0};
+ PH_set_all_pack(packedData, &(hph->desiredSolenoidsState), PH_SET_ALL_LENGTH);
+ HAL_WriteCANPacketRepeating(hph->hcan, packedData, PH_SET_ALL_LENGTH,
+ PH_SET_ALL_FRAME_API, hph->controlPeriod, status);
+}
+
+static HAL_Bool HAL_REV_CheckPHPulseTime(int32_t time) {
+ return ((time > 0) && (time <= HAL_REV_MAX_PULSE_TIME)) ? 1 : 0;
+}
+
+HAL_REVPHHandle HAL_InitializeREVPH(int32_t module,
+ const char* allocationLocation,
+ int32_t* status) {
+ hal::init::CheckInit();
+ if (!HAL_CheckREVPHModuleNumber(module)) {
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PH", 1,
+ kNumREVPHModules, module);
+ return HAL_kInvalidHandle;
+ }
+
+ HAL_REVPHHandle handle;
+ auto hph = REVPHHandles->Allocate(module, &handle, status);
+ if (*status != 0) {
+ if (hph) {
+ hal::SetLastErrorPreviouslyAllocated(status, "REV PH", module,
+ hph->previousAllocation);
+ } else {
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PH", 1,
+ kNumREVPHModules, module);
+ }
+ return HAL_kInvalidHandle; // failed to allocate. Pass error back.
+ }
+
+ HAL_CANHandle hcan =
+ HAL_InitializeCAN(manufacturer, module, deviceType, status);
+
+ if (*status != 0) {
+ REVPHHandles->Free(handle);
+ return HAL_kInvalidHandle;
+ }
+
+ hph->previousAllocation = allocationLocation ? allocationLocation : "";
+ hph->hcan = hcan;
+ hph->controlPeriod = kDefaultControlPeriod;
+
+ // Start closed-loop compressor control by starting solenoid state updates
+ HAL_REV_SendSolenoidsState(hph.get(), status);
+
+ return handle;
+}
+
+void HAL_FreeREVPH(HAL_REVPHHandle handle) {
+ auto hph = REVPHHandles->Get(handle);
+ if (hph == nullptr)
+ return;
+
+ HAL_CleanCAN(hph->hcan);
+
+ REVPHHandles->Free(handle);
+}
+
+HAL_Bool HAL_CheckREVPHModuleNumber(int32_t module) {
+ return module >= 1 && module < kNumREVPDHModules;
+}
+
+HAL_Bool HAL_CheckREVPHSolenoidChannel(int32_t channel) {
+ return channel >= 0 && channel < kNumREVPHChannels;
+}
+
+HAL_Bool HAL_GetREVPHCompressor(HAL_REVPHHandle handle, int32_t* status) {
+ auto ph = REVPHHandles->Get(handle);
+ if (ph == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return false;
+ }
+
+ PH_status0_t status0 = HAL_REV_ReadPHStatus0(ph->hcan, status);
+
+ if (*status != 0) {
+ return false;
+ }
+
+ return status0.compressor_on;
+}
+
+void HAL_SetREVPHClosedLoopControl(HAL_REVPHHandle handle, HAL_Bool enabled,
+ int32_t* status) {
+ // TODO
+}
+
+HAL_Bool HAL_GetREVPHClosedLoopControl(HAL_REVPHHandle handle,
+ int32_t* status) {
+ return false; // TODO
+}
+
+HAL_Bool HAL_GetREVPHPressureSwitch(HAL_REVPHHandle handle, int32_t* status) {
+ auto ph = REVPHHandles->Get(handle);
+ if (ph == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return false;
+ }
+
+ PH_status0_t status0 = HAL_REV_ReadPHStatus0(ph->hcan, status);
+
+ if (*status != 0) {
+ return false;
+ }
+
+ return status0.digital_sensor;
+}
+
+double HAL_GetREVPHCompressorCurrent(HAL_REVPHHandle handle, int32_t* status) {
+ auto ph = REVPHHandles->Get(handle);
+ if (ph == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return 0;
+ }
+
+ PH_status1_t status1 = HAL_REV_ReadPHStatus1(ph->hcan, status);
+
+ if (*status != 0) {
+ return 0;
+ }
+
+ return PH_status1_compressor_current_decode(status1.compressor_current);
+}
+
+double HAL_GetREVPHAnalogPressure(HAL_REVPHHandle handle, int32_t channel,
+ int32_t* status) {
+ auto ph = REVPHHandles->Get(handle);
+ if (ph == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return 0;
+ }
+
+ if (channel < 0 || channel > 1) {
+ *status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid REV Analog Index", 0, 2,
+ channel);
+ return 0;
+ }
+
+ PH_status0_t status0 = HAL_REV_ReadPHStatus0(ph->hcan, status);
+
+ if (*status != 0) {
+ return 0;
+ }
+
+ if (channel == 1) {
+ return PH_status0_analog_0_decode(status0.analog_0);
+ }
+ return PH_status0_analog_1_decode(status0.analog_1);
+}
+
+int32_t HAL_GetREVPHSolenoids(HAL_REVPHHandle handle, int32_t* status) {
+ auto ph = REVPHHandles->Get(handle);
+ if (ph == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return 0;
+ }
+
+ PH_status0_t status0 = HAL_REV_ReadPHStatus0(ph->hcan, status);
+
+ if (*status != 0) {
+ return 0;
+ }
+
+ uint32_t result = status0.channel_0;
+ result |= status0.channel_1 << 1;
+ result |= status0.channel_2 << 2;
+ result |= status0.channel_3 << 3;
+ result |= status0.channel_4 << 4;
+ result |= status0.channel_5 << 5;
+ result |= status0.channel_6 << 6;
+ result |= status0.channel_7 << 7;
+ result |= status0.channel_8 << 8;
+ result |= status0.channel_9 << 9;
+ result |= status0.channel_10 << 10;
+ result |= status0.channel_11 << 11;
+ result |= status0.channel_12 << 12;
+ result |= status0.channel_13 << 13;
+ result |= status0.channel_14 << 14;
+ result |= status0.channel_15 << 15;
+
+ return result;
+}
+
+void HAL_SetREVPHSolenoids(HAL_REVPHHandle handle, int32_t mask, int32_t values,
+ int32_t* status) {
+ auto ph = REVPHHandles->Get(handle);
+ if (ph == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
+ std::scoped_lock lock{ph->solenoidLock};
+ for (int solenoid = 0; solenoid < kNumREVPHChannels; solenoid++) {
+ if (mask & (1 << solenoid)) {
+ // The mask bit for the solenoid is set, so we update the solenoid state
+ REV_SolenoidState desiredSolenoidState =
+ values & (1 << solenoid) ? kSolenoidEnabled : kSolenoidDisabled;
+ HAL_REV_UpdateDesiredPHSolenoidState(ph.get(), solenoid,
+ desiredSolenoidState);
+ }
+ }
+ HAL_REV_SendSolenoidsState(ph.get(), status);
+}
+
+void HAL_FireREVPHOneShot(HAL_REVPHHandle handle, int32_t index, int32_t durMs,
+ int32_t* status) {
+ auto ph = REVPHHandles->Get(handle);
+ if (ph == nullptr) {
+ *status = HAL_HANDLE_ERROR;
+ return;
+ }
+
+ if (index >= kNumREVPHChannels || index < 0) {
+ *status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format("Only [0-15] are valid index values. Requested {}", index));
+ return;
+ }
+
+ if (!HAL_REV_CheckPHPulseTime(durMs)) {
+ *status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format("Time not within expected range [0-65534]. Requested {}",
+ durMs));
+ return;
+ }
+
+ {
+ std::scoped_lock lock{ph->solenoidLock};
+ HAL_REV_UpdateDesiredPHSolenoidState(ph.get(), index,
+ kSolenoidControlledViaPulse);
+ HAL_REV_SendSolenoidsState(ph.get(), status);
+ }
+
+ if (*status != 0) {
+ return;
+ }
+
+ PH_pulse_once_t pulse = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ pulse.pulse_length_ms = durMs;
+
+ // Specify which solenoid should be pulsed
+ // The protocol supports specifying any number of solenoids to be pulsed at
+ // the same time, should that functionality be exposed to users in the future.
+ switch (index) {
+ case 0:
+ pulse.channel_0 = true;
+ break;
+ case 1:
+ pulse.channel_1 = true;
+ break;
+ case 2:
+ pulse.channel_2 = true;
+ break;
+ case 3:
+ pulse.channel_3 = true;
+ break;
+ case 4:
+ pulse.channel_4 = true;
+ break;
+ case 5:
+ pulse.channel_5 = true;
+ break;
+ case 6:
+ pulse.channel_6 = true;
+ break;
+ case 7:
+ pulse.channel_7 = true;
+ break;
+ case 8:
+ pulse.channel_8 = true;
+ break;
+ case 9:
+ pulse.channel_9 = true;
+ break;
+ case 10:
+ pulse.channel_10 = true;
+ break;
+ case 11:
+ pulse.channel_11 = true;
+ break;
+ case 12:
+ pulse.channel_12 = true;
+ break;
+ case 13:
+ pulse.channel_13 = true;
+ break;
+ case 14:
+ pulse.channel_14 = true;
+ break;
+ case 15:
+ pulse.channel_15 = true;
+ break;
+ }
+
+ // Send pulse command
+ uint8_t packedData[PH_PULSE_ONCE_LENGTH] = {0};
+ PH_pulse_once_pack(packedData, &pulse, PH_PULSE_ONCE_LENGTH);
+ HAL_WriteCANPacket(ph->hcan, packedData, PH_PULSE_ONCE_LENGTH,
+ PH_PULSE_ONCE_FRAME_API, status);
+}
diff --git a/hal/src/main/native/athena/Relay.cpp b/hal/src/main/native/athena/Relay.cpp
index 4dffa36..a01dd9d 100644
--- a/hal/src/main/native/athena/Relay.cpp
+++ b/hal/src/main/native/athena/Relay.cpp
@@ -1,14 +1,14 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/Relay.h"
+#include <string>
+
#include "DigitalInternal.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/handles/IndexedHandleResource.h"
@@ -19,6 +19,7 @@
struct Relay {
uint8_t channel;
bool fwd;
+ std::string previousAllocation;
};
} // namespace
@@ -29,46 +30,54 @@
// Create a mutex to protect changes to the relay values
static wpi::mutex digitalRelayMutex;
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeRelay() {
static IndexedHandleResource<HAL_RelayHandle, Relay, kNumRelayChannels,
HAL_HandleEnum::Relay>
rH;
relayHandles = &rH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
HAL_RelayHandle HAL_InitializeRelayPort(HAL_PortHandle portHandle, HAL_Bool fwd,
+ const char* allocationLocation,
int32_t* status) {
hal::init::CheckInit();
initializeDigital(status);
- if (*status != 0) return HAL_kInvalidHandle;
-
- int16_t channel = getPortHandleChannel(portHandle);
- if (channel == InvalidHandleIndex) {
- *status = PARAMETER_OUT_OF_RANGE;
+ if (*status != 0) {
return HAL_kInvalidHandle;
}
- if (!fwd) channel += kNumRelayHeaders; // add 4 to reverse channels
-
- auto handle = relayHandles->Allocate(channel, status);
-
- if (*status != 0)
- return HAL_kInvalidHandle; // failed to allocate. Pass error back.
-
- auto port = relayHandles->Get(handle);
- if (port == nullptr) { // would only occur on thread issue.
- *status = HAL_HANDLE_ERROR;
+ int16_t channel = getPortHandleChannel(portHandle);
+ if (channel == InvalidHandleIndex || channel >= kNumRelayChannels) {
+ *status = RESOURCE_OUT_OF_RANGE;
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Relay", 0,
+ kNumRelayChannels, channel);
return HAL_kInvalidHandle;
}
if (!fwd) {
+ channel += kNumRelayHeaders; // add 4 to reverse channels
+ }
+
+ HAL_RelayHandle handle;
+ auto port = relayHandles->Allocate(channel, &handle, status);
+
+ if (*status != 0) {
+ if (port) {
+ hal::SetLastErrorPreviouslyAllocated(status, "Relay", channel,
+ port->previousAllocation);
+ } else {
+ hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Relay", 0,
+ kNumRelayChannels, channel);
+ }
+ return HAL_kInvalidHandle; // failed to allocate. Pass error back.
+ }
+
+ if (!fwd) {
// Subtract number of headers to put channel in range
channel -= kNumRelayHeaders;
@@ -78,6 +87,7 @@
}
port->channel = static_cast<uint8_t>(channel);
+ port->previousAllocation = allocationLocation ? allocationLocation : "";
return handle;
}
@@ -108,7 +118,9 @@
relays = relaySystem->readValue_Reverse(status);
}
- if (*status != 0) return; // bad status read
+ if (*status != 0) {
+ return; // bad status read
+ }
if (on) {
relays |= 1 << port->channel;
diff --git a/hal/src/main/native/athena/SPI.cpp b/hal/src/main/native/athena/SPI.cpp
index 37c5f0e..1121fd8 100644
--- a/hal/src/main/native/athena/SPI.cpp
+++ b/hal/src/main/native/athena/SPI.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/SPI.h"
@@ -14,13 +11,15 @@
#include <array>
#include <atomic>
+#include <cstdio>
#include <cstring>
+#include <fmt/format.h>
#include <wpi/mutex.h>
-#include <wpi/raw_ostream.h>
#include "DigitalInternal.h"
#include "HALInitializer.h"
+#include "HALInternal.h"
#include "hal/DIO.h"
#include "hal/HAL.h"
#include "hal/handles/HandlesInternal.h"
@@ -54,17 +53,17 @@
// SPI engine conflicts with any other chip selects on the same SPI device.
// There are two SPI devices: one for ports 0-3 (onboard), the other for port
// 4 (MXP).
- if (!spiAutoRunning) return false;
+ if (!spiAutoRunning) {
+ return false;
+ }
std::scoped_lock lock(spiAutoMutex);
return (spiAutoPort >= 0 && spiAutoPort <= 3 && port >= 0 && port <= 3) ||
(spiAutoPort == 4 && port == 4);
}
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeSPI() {}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
@@ -73,19 +72,21 @@
if (spiPortCount.fetch_add(1) == 0) {
// Have not been initialized yet
initializeDigital(status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
// MISO
if ((digitalHandles[3] = HAL_InitializeDIOPort(createPortHandleForSPI(29),
- false, status)) ==
+ false, nullptr, status)) ==
HAL_kInvalidHandle) {
- std::printf("Failed to allocate DIO 29 (MISO)\n");
+ std::puts("Failed to allocate DIO 29 (MISO)");
return;
}
// MOSI
if ((digitalHandles[4] = HAL_InitializeDIOPort(createPortHandleForSPI(30),
- false, status)) ==
+ false, nullptr, status)) ==
HAL_kInvalidHandle) {
- std::printf("Failed to allocate DIO 30 (MOSI)\n");
+ std::puts("Failed to allocate DIO 30 (MOSI)");
HAL_FreeDIOPort(digitalHandles[3]); // free the first port allocated
return;
}
@@ -104,20 +105,28 @@
hal::init::CheckInit();
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format("Serial port must be between 0 and {}. Requested {}",
+ kSpiMaxHandles, static_cast<int>(port)));
return;
}
int handle;
- if (HAL_GetSPIHandle(port) != 0) return;
+ if (HAL_GetSPIHandle(port) != 0) {
+ return;
+ }
switch (port) {
case HAL_SPI_kOnboardCS0:
CommonSPIPortInit(status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
// CS0 is not a DIO port, so nothing to allocate
handle = open("/dev/spidev0.0", O_RDWR);
if (handle < 0) {
- std::printf("Failed to open SPI port %d: %s\n", port,
- std::strerror(errno));
+ fmt::print("Failed to open SPI port {}: {}\n", port,
+ std::strerror(errno));
CommonSPIPortFree();
return;
}
@@ -125,19 +134,21 @@
break;
case HAL_SPI_kOnboardCS1:
CommonSPIPortInit(status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
// CS1, Allocate
if ((digitalHandles[0] = HAL_InitializeDIOPort(createPortHandleForSPI(26),
- false, status)) ==
+ false, nullptr, status)) ==
HAL_kInvalidHandle) {
- std::printf("Failed to allocate DIO 26 (CS1)\n");
+ std::puts("Failed to allocate DIO 26 (CS1)");
CommonSPIPortFree();
return;
}
handle = open("/dev/spidev0.1", O_RDWR);
if (handle < 0) {
- std::printf("Failed to open SPI port %d: %s\n", port,
- std::strerror(errno));
+ fmt::print("Failed to open SPI port {}: {}\n", port,
+ std::strerror(errno));
CommonSPIPortFree();
HAL_FreeDIOPort(digitalHandles[0]);
return;
@@ -146,19 +157,21 @@
break;
case HAL_SPI_kOnboardCS2:
CommonSPIPortInit(status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
// CS2, Allocate
if ((digitalHandles[1] = HAL_InitializeDIOPort(createPortHandleForSPI(27),
- false, status)) ==
+ false, nullptr, status)) ==
HAL_kInvalidHandle) {
- std::printf("Failed to allocate DIO 27 (CS2)\n");
+ std::puts("Failed to allocate DIO 27 (CS2)");
CommonSPIPortFree();
return;
}
handle = open("/dev/spidev0.2", O_RDWR);
if (handle < 0) {
- std::printf("Failed to open SPI port %d: %s\n", port,
- std::strerror(errno));
+ fmt::print("Failed to open SPI port {}: {}\n", port,
+ std::strerror(errno));
CommonSPIPortFree();
HAL_FreeDIOPort(digitalHandles[1]);
return;
@@ -167,19 +180,21 @@
break;
case HAL_SPI_kOnboardCS3:
CommonSPIPortInit(status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
// CS3, Allocate
if ((digitalHandles[2] = HAL_InitializeDIOPort(createPortHandleForSPI(28),
- false, status)) ==
+ false, nullptr, status)) ==
HAL_kInvalidHandle) {
- std::printf("Failed to allocate DIO 28 (CS3)\n");
+ std::puts("Failed to allocate DIO 28 (CS3)");
CommonSPIPortFree();
return;
}
handle = open("/dev/spidev0.3", O_RDWR);
if (handle < 0) {
- std::printf("Failed to open SPI port %d: %s\n", port,
- std::strerror(errno));
+ fmt::print("Failed to open SPI port {}: {}\n", port,
+ std::strerror(errno));
CommonSPIPortFree();
HAL_FreeDIOPort(digitalHandles[2]);
return;
@@ -188,32 +203,34 @@
break;
case HAL_SPI_kMXP:
initializeDigital(status);
- if (*status != 0) return;
+ if (*status != 0) {
+ return;
+ }
if ((digitalHandles[5] = HAL_InitializeDIOPort(createPortHandleForSPI(14),
- false, status)) ==
+ false, nullptr, status)) ==
HAL_kInvalidHandle) {
- wpi::outs() << "Failed to allocate DIO 14\n";
+ std::puts("Failed to allocate DIO 14");
return;
}
if ((digitalHandles[6] = HAL_InitializeDIOPort(createPortHandleForSPI(15),
- false, status)) ==
+ false, nullptr, status)) ==
HAL_kInvalidHandle) {
- wpi::outs() << "Failed to allocate DIO 15\n";
+ std::puts("Failed to allocate DIO 15");
HAL_FreeDIOPort(digitalHandles[5]); // free the first port allocated
return;
}
if ((digitalHandles[7] = HAL_InitializeDIOPort(createPortHandleForSPI(16),
- false, status)) ==
+ false, nullptr, status)) ==
HAL_kInvalidHandle) {
- wpi::outs() << "Failed to allocate DIO 16\n";
+ std::puts("Failed to allocate DIO 16");
HAL_FreeDIOPort(digitalHandles[5]); // free the first port allocated
HAL_FreeDIOPort(digitalHandles[6]); // free the second port allocated
return;
}
if ((digitalHandles[8] = HAL_InitializeDIOPort(createPortHandleForSPI(17),
- false, status)) ==
+ false, nullptr, status)) ==
HAL_kInvalidHandle) {
- wpi::outs() << "Failed to allocate DIO 17\n";
+ std::puts("Failed to allocate DIO 17");
HAL_FreeDIOPort(digitalHandles[5]); // free the first port allocated
HAL_FreeDIOPort(digitalHandles[6]); // free the second port allocated
HAL_FreeDIOPort(digitalHandles[7]); // free the third port allocated
@@ -223,8 +240,8 @@
digitalSystem->readEnableMXPSpecialFunction(status) | 0x00F0, status);
handle = open("/dev/spidev1.0", O_RDWR);
if (handle < 0) {
- std::printf("Failed to open SPI port %d: %s\n", port,
- std::strerror(errno));
+ fmt::print("Failed to open SPI port {}: {}\n", port,
+ std::strerror(errno));
HAL_FreeDIOPort(digitalHandles[5]); // free the first port allocated
HAL_FreeDIOPort(digitalHandles[6]); // free the second port allocated
HAL_FreeDIOPort(digitalHandles[7]); // free the third port allocated
@@ -235,6 +252,8 @@
break;
default:
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status, fmt::format("Invalid SPI port {}", static_cast<int>(port)));
break;
}
}
@@ -245,7 +264,9 @@
return -1;
}
- if (SPIInUseByAuto(port)) return -1;
+ if (SPIInUseByAuto(port)) {
+ return -1;
+ }
struct spi_ioc_transfer xfer;
std::memset(&xfer, 0, sizeof(xfer));
@@ -263,7 +284,9 @@
return -1;
}
- if (SPIInUseByAuto(port)) return -1;
+ if (SPIInUseByAuto(port)) {
+ return -1;
+ }
struct spi_ioc_transfer xfer;
std::memset(&xfer, 0, sizeof(xfer));
@@ -279,7 +302,9 @@
return -1;
}
- if (SPIInUseByAuto(port)) return -1;
+ if (SPIInUseByAuto(port)) {
+ return -1;
+ }
struct spi_ioc_transfer xfer;
std::memset(&xfer, 0, sizeof(xfer));
@@ -357,6 +382,10 @@
void HAL_SetSPIChipSelectActiveHigh(HAL_SPIPort port, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format("Serial port must be between 0 and {}. Requested {}",
+ kSpiMaxHandles, static_cast<int>(port)));
return;
}
@@ -372,6 +401,10 @@
void HAL_SetSPIChipSelectActiveLow(HAL_SPIPort port, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format("Serial port must be between 0 and {}. Requested {}",
+ kSpiMaxHandles, static_cast<int>(port)));
return;
}
@@ -436,6 +469,10 @@
void HAL_InitSPIAuto(HAL_SPIPort port, int32_t bufferSize, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format("Serial port must be between 0 and {}. Requested {}",
+ kSpiMaxHandles, static_cast<int>(port)));
return;
}
@@ -467,11 +504,17 @@
void HAL_FreeSPIAuto(HAL_SPIPort port, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format("Serial port must be between 0 and {}. Requested {}",
+ kSpiMaxHandles, static_cast<int>(port)));
return;
}
std::scoped_lock lock(spiAutoMutex);
- if (spiAutoPort != port) return;
+ if (spiAutoPort != port) {
+ return;
+ }
spiAutoPort = kSpiMaxHandles;
// disable by setting to internal clock and setting rate=0
@@ -567,11 +610,21 @@
int32_t* status) {
if (dataSize < 0 || dataSize > 32) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format(
+ "Data size must be between 0 and 32 inclusive. Requested {}",
+ dataSize));
return;
}
if (zeroSize < 0 || zeroSize > 127) {
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(
+ status,
+ fmt::format(
+ "Zero size must be between 0 and 127 inclusive. Requested {}",
+ zeroSize));
return;
}
diff --git a/hal/src/main/native/athena/SerialPort.cpp b/hal/src/main/native/athena/SerialPort.cpp
index 7ef9b70..374986b 100644
--- a/hal/src/main/native/athena/SerialPort.cpp
+++ b/hal/src/main/native/athena/SerialPort.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/SerialPort.h"
@@ -22,6 +19,9 @@
#include <string>
#include <thread>
+#include <fmt/format.h>
+
+#include "HALInternal.h"
#include "hal/cpp/SerialHelper.h"
#include "hal/handles/HandlesInternal.h"
#include "hal/handles/IndexedHandleResource.h"
@@ -44,16 +44,14 @@
HAL_HandleEnum::SerialPort>* serialPortHandles;
} // namespace hal
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeSerialPort() {
static IndexedHandleResource<HAL_SerialPortHandle, SerialPort, 4,
HAL_HandleEnum::SerialPort>
spH;
serialPortHandles = &spH;
}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
using namespace hal;
@@ -75,22 +73,20 @@
HAL_SerialPortHandle HAL_InitializeSerialPortDirect(HAL_SerialPort port,
const char* portName,
int32_t* status) {
- auto handle = serialPortHandles->Allocate(static_cast<int16_t>(port), status);
+ HAL_SerialPortHandle handle;
+ auto serialPort =
+ serialPortHandles->Allocate(static_cast<int16_t>(port), &handle, status);
if (*status != 0) {
return HAL_kInvalidHandle;
}
- auto serialPort = serialPortHandles->Get(handle);
-
- if (serialPort == nullptr) {
- *status = HAL_HANDLE_ERROR;
- return HAL_kInvalidHandle;
- }
-
serialPort->portId = open(portName, O_RDWR | O_NOCTTY);
if (serialPort->portId < 0) {
*status = errno;
+ if (*status == EACCES) {
+ *status = HAL_CONSOLE_OUT_ENABLED_ERROR;
+ }
serialPortHandles->Free(handle);
return HAL_kInvalidHandle;
}
@@ -193,6 +189,7 @@
BAUDCASE(4000000)
default:
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status, fmt::format("Invalid BaudRate: {}", baud));
return;
}
int err = cfsetospeed(&port->tty, static_cast<speed_t>(port->baudRate));
@@ -235,6 +232,7 @@
break;
default:
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status, fmt::format("Invalid data bits: {}", bits));
return;
}
@@ -282,6 +280,7 @@
break;
default:
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status, fmt::format("Invalid parity bits: {}", parity));
return;
}
@@ -309,6 +308,7 @@
break;
default:
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status, fmt::format("Invalid stop bits: {}", stopBits));
return;
}
@@ -344,6 +344,7 @@
break;
default:
*status = PARAMETER_OUT_OF_RANGE;
+ hal::SetLastError(status, fmt::format("Invalid fc bits: {}", flow));
return;
}
@@ -417,7 +418,9 @@
int32_t HAL_ReadSerial(HAL_SerialPortHandle handle, char* buffer, int32_t count,
int32_t* status) {
// Don't do anything if 0 bytes were requested
- if (count == 0) return 0;
+ if (count == 0) {
+ return 0;
+ }
auto port = serialPortHandles->Get(handle);
if (!port) {
diff --git a/hal/src/main/native/athena/SimDevice.cpp b/hal/src/main/native/athena/SimDevice.cpp
index 94a65d4..3a15f46 100644
--- a/hal/src/main/native/athena/SimDevice.cpp
+++ b/hal/src/main/native/athena/SimDevice.cpp
@@ -1,32 +1,38 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2019 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/SimDevice.h"
extern "C" {
-HAL_SimDeviceHandle HAL_CreateSimDevice(const char* name) { return 0; }
+HAL_SimDeviceHandle HAL_CreateSimDevice(const char* name) {
+ return 0;
+}
void HAL_FreeSimDevice(HAL_SimDeviceHandle handle) {}
HAL_SimValueHandle HAL_CreateSimValue(HAL_SimDeviceHandle device,
- const char* name, HAL_Bool readonly,
+ const char* name, int32_t direction,
const struct HAL_Value* initialValue) {
return 0;
}
HAL_SimValueHandle HAL_CreateSimValueEnum(HAL_SimDeviceHandle device,
- const char* name, HAL_Bool readonly,
+ const char* name, int32_t direction,
int32_t numOptions,
const char** options,
int32_t initialValue) {
return 0;
}
+HAL_SimValueHandle HAL_CreateSimValueEnumDouble(
+ HAL_SimDeviceHandle device, const char* name, int32_t direction,
+ int32_t numOptions, const char** options, const double* optionValues,
+ int32_t initialValue) {
+ return 0;
+}
+
void HAL_GetSimValue(HAL_SimValueHandle handle, struct HAL_Value* value) {
value->type = HAL_UNASSIGNED;
}
@@ -34,6 +40,8 @@
void HAL_SetSimValue(HAL_SimValueHandle handle, const struct HAL_Value* value) {
}
+void HAL_ResetSimValue(HAL_SimValueHandle handle) {}
+
hal::SimDevice::SimDevice(const char* name, int index) {}
hal::SimDevice::SimDevice(const char* name, int index, int channel) {}
diff --git a/hal/src/main/native/athena/Solenoid.cpp b/hal/src/main/native/athena/Solenoid.cpp
deleted file mode 100644
index ab563b3..0000000
--- a/hal/src/main/native/athena/Solenoid.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
-
-#include "hal/Solenoid.h"
-
-#include "HALInitializer.h"
-#include "PCMInternal.h"
-#include "PortsInternal.h"
-#include "ctre/PCM.h"
-#include "hal/Errors.h"
-#include "hal/handles/HandlesInternal.h"
-#include "hal/handles/IndexedHandleResource.h"
-
-namespace {
-
-struct Solenoid {
- uint8_t module;
- uint8_t channel;
-};
-
-} // namespace
-
-using namespace hal;
-
-static IndexedHandleResource<HAL_SolenoidHandle, Solenoid,
- kNumPCMModules * kNumSolenoidChannels,
- HAL_HandleEnum::Solenoid>* solenoidHandles;
-
-namespace hal {
-namespace init {
-void InitializeSolenoid() {
- static IndexedHandleResource<HAL_SolenoidHandle, Solenoid,
- kNumPCMModules * kNumSolenoidChannels,
- HAL_HandleEnum::Solenoid>
- sH;
- solenoidHandles = &sH;
-}
-} // namespace init
-} // namespace hal
-
-extern "C" {
-
-HAL_SolenoidHandle HAL_InitializeSolenoidPort(HAL_PortHandle portHandle,
- int32_t* status) {
- hal::init::CheckInit();
- int16_t channel = getPortHandleChannel(portHandle);
- int16_t module = getPortHandleModule(portHandle);
- if (channel == InvalidHandleIndex) {
- *status = HAL_HANDLE_ERROR;
- return HAL_kInvalidHandle;
- }
-
- // initializePCM will check the module
- if (!HAL_CheckSolenoidChannel(channel)) {
- *status = RESOURCE_OUT_OF_RANGE;
- return HAL_kInvalidHandle;
- }
-
- initializePCM(module, status);
- if (*status != 0) {
- return HAL_kInvalidHandle;
- }
-
- auto handle = solenoidHandles->Allocate(
- module * kNumSolenoidChannels + channel, status);
- if (*status != 0) {
- return HAL_kInvalidHandle;
- }
- auto solenoidPort = solenoidHandles->Get(handle);
- if (solenoidPort == nullptr) { // would only occur on thread issues
- *status = HAL_HANDLE_ERROR;
- return HAL_kInvalidHandle;
- }
- solenoidPort->module = static_cast<uint8_t>(module);
- solenoidPort->channel = static_cast<uint8_t>(channel);
-
- return handle;
-}
-
-void HAL_FreeSolenoidPort(HAL_SolenoidHandle solenoidPortHandle) {
- solenoidHandles->Free(solenoidPortHandle);
-}
-
-HAL_Bool HAL_CheckSolenoidModule(int32_t module) {
- return module < kNumPCMModules && module >= 0;
-}
-
-HAL_Bool HAL_CheckSolenoidChannel(int32_t channel) {
- return channel < kNumSolenoidChannels && channel >= 0;
-}
-
-HAL_Bool HAL_GetSolenoid(HAL_SolenoidHandle solenoidPortHandle,
- int32_t* status) {
- auto port = solenoidHandles->Get(solenoidPortHandle);
- if (port == nullptr) {
- *status = HAL_HANDLE_ERROR;
- return false;
- }
- bool value;
-
- *status = PCM_modules[port->module]->GetSolenoid(port->channel, value);
-
- return value;
-}
-
-int32_t HAL_GetAllSolenoids(int32_t module, int32_t* status) {
- if (!checkPCMInit(module, status)) return 0;
- uint8_t value;
-
- *status = PCM_modules[module]->GetAllSolenoids(value);
-
- return value;
-}
-
-void HAL_SetSolenoid(HAL_SolenoidHandle solenoidPortHandle, HAL_Bool value,
- int32_t* status) {
- auto port = solenoidHandles->Get(solenoidPortHandle);
- if (port == nullptr) {
- *status = HAL_HANDLE_ERROR;
- return;
- }
-
- *status = PCM_modules[port->module]->SetSolenoid(port->channel, value);
-}
-
-void HAL_SetAllSolenoids(int32_t module, int32_t state, int32_t* status) {
- if (!checkPCMInit(module, status)) return;
-
- *status = PCM_modules[module]->SetAllSolenoids(state);
-}
-
-int32_t HAL_GetPCMSolenoidBlackList(int32_t module, int32_t* status) {
- if (!checkPCMInit(module, status)) return 0;
- uint8_t value;
-
- *status = PCM_modules[module]->GetSolenoidBlackList(value);
-
- return value;
-}
-HAL_Bool HAL_GetPCMSolenoidVoltageStickyFault(int32_t module, int32_t* status) {
- if (!checkPCMInit(module, status)) return 0;
- bool value;
-
- *status = PCM_modules[module]->GetSolenoidStickyFault(value);
-
- return value;
-}
-HAL_Bool HAL_GetPCMSolenoidVoltageFault(int32_t module, int32_t* status) {
- if (!checkPCMInit(module, status)) return false;
- bool value;
-
- *status = PCM_modules[module]->GetSolenoidFault(value);
-
- return value;
-}
-void HAL_ClearAllPCMStickyFaults(int32_t module, int32_t* status) {
- if (!checkPCMInit(module, status)) return;
-
- *status = PCM_modules[module]->ClearStickyFaults();
-}
-
-void HAL_SetOneShotDuration(HAL_SolenoidHandle solenoidPortHandle,
- int32_t durMS, int32_t* status) {
- auto port = solenoidHandles->Get(solenoidPortHandle);
- if (port == nullptr) {
- *status = HAL_HANDLE_ERROR;
- return;
- }
-
- *status =
- PCM_modules[port->module]->SetOneShotDurationMs(port->channel, durMS);
-}
-
-void HAL_FireOneShot(HAL_SolenoidHandle solenoidPortHandle, int32_t* status) {
- auto port = solenoidHandles->Get(solenoidPortHandle);
- if (port == nullptr) {
- *status = HAL_HANDLE_ERROR;
- return;
- }
-
- *status = PCM_modules[port->module]->FireOneShotSolenoid(port->channel);
-}
-} // extern "C"
diff --git a/hal/src/main/native/athena/Threads.cpp b/hal/src/main/native/athena/Threads.cpp
index 95d1f59..aa55b56 100644
--- a/hal/src/main/native/athena/Threads.cpp
+++ b/hal/src/main/native/athena/Threads.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/Threads.h"
@@ -12,11 +9,9 @@
#include "hal/Errors.h"
-namespace hal {
-namespace init {
+namespace hal::init {
void InitializeThreads() {}
-} // namespace init
-} // namespace hal
+} // namespace hal::init
extern "C" {
@@ -37,8 +32,8 @@
return sch.sched_priority;
} else {
*isRealTime = false;
- // 0 is the only suppored priority for non-realtime, so scale to 1
- return 1;
+ // 0 is the only supported priority for non-real-time
+ return 0;
}
}
@@ -69,11 +64,13 @@
int policy;
pthread_getschedparam(*reinterpret_cast<const pthread_t*>(handle), &policy,
&sch);
- if (scheduler == SCHED_FIFO || scheduler == SCHED_RR)
+ if (scheduler == SCHED_FIFO || scheduler == SCHED_RR) {
sch.sched_priority = priority;
- else
+ } else {
// Only need to set 0 priority for non RT thread
sch.sched_priority = 0;
+ }
+
if (pthread_setschedparam(*reinterpret_cast<const pthread_t*>(handle),
scheduler, &sch)) {
*status = HAL_THREAD_PRIORITY_ERROR;
diff --git a/hal/src/main/native/athena/cpp/SerialHelper.cpp b/hal/src/main/native/athena/cpp/SerialHelper.cpp
index 2156147..3831769 100644
--- a/hal/src/main/native/athena/cpp/SerialHelper.cpp
+++ b/hal/src/main/native/athena/cpp/SerialHelper.cpp
@@ -1,18 +1,16 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/cpp/SerialHelper.h"
#include <algorithm>
#include <cstdio>
#include <cstring>
+#include <string_view>
-#include <wpi/FileSystem.h>
-#include <wpi/StringRef.h>
+#include <wpi/StringExtras.h>
+#include <wpi/fs.h>
#include "hal/Errors.h"
#include "visa/visa.h"
@@ -56,7 +54,7 @@
return "";
// Error
} else {
- return m_visaResource[visaIndex].str();
+ return std::string{m_visaResource[visaIndex].str()};
}
}
@@ -83,7 +81,7 @@
return "";
// Error
} else {
- return m_osResource[osIndex].str();
+ return std::string{m_osResource[osIndex].str()};
}
}
@@ -139,8 +137,8 @@
std::sort(m_sortedHubPath.begin(), m_sortedHubPath.end(),
[](const wpi::SmallVectorImpl<char>& lhs,
const wpi::SmallVectorImpl<char>& rhs) -> int {
- wpi::StringRef lhsRef(lhs.begin(), lhs.size());
- wpi::StringRef rhsRef(rhs.begin(), rhs.size());
+ std::string_view lhsRef(lhs.begin(), lhs.size());
+ std::string_view rhsRef(rhs.begin(), rhs.size());
return lhsRef.compare(rhsRef);
});
}
@@ -150,15 +148,15 @@
wpi::SmallVector<wpi::SmallString<16>, 4> sortedVec;
for (auto& str : m_sortedHubPath) {
for (size_t i = 0; i < m_unsortedHubPath.size(); i++) {
- if (wpi::StringRef{m_unsortedHubPath[i].begin(),
- m_unsortedHubPath[i].size()}
- .equals(wpi::StringRef{str.begin(), str.size()})) {
+ if (wpi::equals(std::string_view{m_unsortedHubPath[i].begin(),
+ m_unsortedHubPath[i].size()},
+ std::string_view{str.begin(), str.size()})) {
sortedVec.push_back(vec[i]);
break;
}
}
}
- vec = sortedVec;
+ vec.swap(sortedVec);
}
void SerialHelper::QueryHubPaths(int32_t* status) {
@@ -194,73 +192,82 @@
// 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) goto done;
+ if (*status < 0)
+ goto done;
*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) goto done;
- if (closeStatus < 0) goto done;
+ if (*status < 0)
+ goto done;
+ if (closeStatus < 0)
+ goto done;
*status = 0;
// split until (/dev/
- wpi::StringRef devNameRef = wpi::StringRef{osName}.split("(/dev/").second;
+ std::string_view devNameRef = wpi::split(osName, "(/dev/").second;
// String not found, continue
- if (devNameRef.equals("")) continue;
+ if (wpi::equals(devNameRef, ""))
+ continue;
// Split at )
- wpi::StringRef matchString = devNameRef.split(')').first;
- if (matchString.equals(devNameRef)) continue;
+ std::string_view matchString = wpi::split(devNameRef, ')').first;
+ 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 = wpi::sys::fs::recursive_directory_iterator(
- "/sys/devices/soc0", ec, false);
- p != wpi::sys::fs::recursive_directory_iterator(); p.increment(ec)) {
- if (ec) break;
- wpi::StringRef path{p->path()};
- if (path.find("amba") == wpi::StringRef::npos) continue;
- if (path.find("usb") == wpi::StringRef::npos) continue;
- if (path.find(matchString) == wpi::StringRef::npos) continue;
+ for (auto& p : fs::recursive_directory_iterator("/sys/devices/soc0", ec)) {
+ if (ec)
+ break;
+ std::string path = p.path();
+ if (path.find("amba") == std::string::npos)
+ continue;
+ if (path.find("usb") == std::string::npos)
+ continue;
+ if (path.find(matchString) == std::string::npos)
+ continue;
- wpi::SmallVector<wpi::StringRef, 16> pathSplitVec;
+ wpi::SmallVector<std::string_view, 16> pathSplitVec;
// Split path into individual directories
- path.split(pathSplitVec, '/', -1, false);
+ wpi::split(path, pathSplitVec, '/', -1, false);
// Find each individual item index
int findusb = -1;
int findtty = -1;
int findregex = -1;
for (size_t i = 0; i < pathSplitVec.size(); i++) {
- if (findusb == -1 && pathSplitVec[i].equals("usb1")) {
+ if (findusb == -1 && wpi::equals(pathSplitVec[i], "usb1")) {
findusb = i;
}
- if (findtty == -1 && pathSplitVec[i].equals("tty")) {
+ if (findtty == -1 && wpi::equals(pathSplitVec[i], "tty")) {
findtty = i;
}
- if (findregex == -1 && pathSplitVec[i].equals(matchString)) {
+ if (findregex == -1 && wpi::equals(pathSplitVec[i], matchString)) {
findregex = i;
}
}
// Get the index for our device
int hubIndex = findtty;
- if (findtty == -1) hubIndex = findregex;
+ if (findtty == -1)
+ hubIndex = findregex;
int devStart = findusb + 1;
- if (hubIndex < devStart) continue;
+ if (hubIndex < devStart)
+ continue;
// Add our devices to our list
m_unsortedHubPath.emplace_back(
- wpi::StringRef{pathSplitVec[hubIndex - 2]});
+ std::string_view{pathSplitVec[hubIndex - 2]});
m_visaResource.emplace_back(desc);
m_osResource.emplace_back(
- wpi::StringRef{osName}.split("(").second.split(")").first);
+ wpi::split(wpi::split(osName, "(").second, ")").first);
break;
}
}
@@ -285,8 +292,9 @@
if (portString.empty()) {
for (size_t i = 0; i < 2; i++) {
// Remove all used ports
- auto idx = std::find(m_sortedHubPath.begin(), m_sortedHubPath.end(),
- m_usbNames[i]);
+ auto idx = std::find_if(
+ m_sortedHubPath.begin(), m_sortedHubPath.end(),
+ [&](const auto& s) { return wpi::equals(s, m_usbNames[i]); });
if (idx != m_sortedHubPath.end()) {
// found
m_sortedHubPath.erase(idx);
@@ -321,7 +329,7 @@
int retIndex = -1;
for (size_t i = 0; i < m_sortedHubPath.size(); i++) {
- if (m_sortedHubPath[i].equals(portString)) {
+ if (wpi::equals(m_sortedHubPath[i], portString)) {
retIndex = i;
break;
}
diff --git a/hal/src/main/native/athena/ctre/CtreCanNode.cpp b/hal/src/main/native/athena/ctre/CtreCanNode.cpp
deleted file mode 100644
index 440bebd..0000000
--- a/hal/src/main/native/athena/ctre/CtreCanNode.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
-
-#include "CtreCanNode.h"
-#include "FRC_NetworkCommunication/CANSessionMux.h"
-#include <string.h> // memset
-
-static const UINT32 kFullMessageIDMask = 0x1fffffff;
-
-CtreCanNode::CtreCanNode(UINT8 deviceNumber)
-{
- _deviceNumber = deviceNumber;
-}
-CtreCanNode::~CtreCanNode()
-{
-}
-void CtreCanNode::RegisterRx(uint32_t arbId)
-{
- /* no need to do anything, we just use new API to poll last received message */
-}
-/**
- * Schedule a CAN Frame for periodic transmit.
- * @param arbId CAN Frame Arbitration ID. Set BIT31 for 11bit ids, otherwise we use 29bit ids.
- * @param periodMs Period to transmit CAN frame. Pass 0 for one-shot, which also disables that ArbID's preceding periodic transmit.
- * @param dlc Number of bytes to transmit (0 to 8).
- * @param initialFrame Ptr to the frame data to schedule for transmitting. Passing null will result
- * in defaulting to zero data value.
- */
-void CtreCanNode::RegisterTx(uint32_t arbId, uint32_t periodMs, uint32_t dlc, const uint8_t * initialFrame)
-{
- int32_t status = 0;
- if(dlc > 8)
- dlc = 8;
- txJob_t job = {0};
- job.arbId = arbId;
- job.periodMs = periodMs;
- job.dlc = dlc;
- if(initialFrame){
- /* caller wants to specify original data */
- memcpy(job.toSend, initialFrame, dlc);
- }
- _txJobs[arbId] = job;
- FRC_NetworkCommunication_CANSessionMux_sendMessage( job.arbId,
- job.toSend,
- job.dlc,
- job.periodMs,
- &status);
-}
-/**
- * Schedule a CAN Frame for periodic transmit. Assume eight byte DLC and zero value for initial transmission.
- * @param arbId CAN Frame Arbitration ID. Set BIT31 for 11bit ids, otherwise we use 29bit ids.
- * @param periodMs Period to transmit CAN frame. Pass 0 for one-shot, which also disables that ArbID's preceding periodic transmit.
- */
-void CtreCanNode::RegisterTx(uint32_t arbId, uint32_t periodMs)
-{
- RegisterTx(arbId,periodMs, 8, 0);
-}
-/**
- * Remove a CAN frame Arbid to stop transmission.
- * @param arbId CAN Frame Arbitration ID. Set BIT31 for 11bit ids, otherwise we use 29bit ids.
- */
-void CtreCanNode::UnregisterTx(uint32_t arbId)
-{
- /* set period to zero */
- ChangeTxPeriod(arbId, 0);
- /* look and remove */
- txJobs_t::iterator iter = _txJobs.find(arbId);
- if(iter != _txJobs.end()) {
- _txJobs.erase(iter);
- }
-}
-static int64_t GetTimeMs() {
- std::chrono::time_point < std::chrono::system_clock > now;
- now = std::chrono::system_clock::now();
- auto duration = now.time_since_epoch();
- auto millis = std::chrono::duration_cast < std::chrono::milliseconds
- > (duration).count();
- return (int64_t) millis;
-}
-CTR_Code CtreCanNode::GetRx(uint32_t arbId,uint8_t * dataBytes, uint32_t timeoutMs)
-{
- CTR_Code retval = CTR_OKAY;
- int32_t status = 0;
- uint8_t len = 0;
- uint32_t timeStamp;
- /* cap timeout at 999ms */
- if(timeoutMs > 999)
- timeoutMs = 999;
- FRC_NetworkCommunication_CANSessionMux_receiveMessage(&arbId,kFullMessageIDMask,dataBytes,&len,&timeStamp,&status);
- std::scoped_lock lock(_lck);
- if(status == 0){
- /* fresh update */
- rxEvent_t & r = _rxRxEvents[arbId]; /* lookup entry or make a default new one with all zeroes */
- r.time = GetTimeMs();
- memcpy(r.bytes, dataBytes, 8); /* fill in databytes */
- }else{
- /* did not get the message */
- rxRxEvents_t::iterator i = _rxRxEvents.find(arbId);
- if(i == _rxRxEvents.end()){
- /* we've never gotten this mesage */
- retval = CTR_RxTimeout;
- /* fill caller's buffer with zeros */
- memset(dataBytes,0,8);
- }else{
- /* we've gotten this message before but not recently */
- memcpy(dataBytes,i->second.bytes,8);
- /* get the time now */
- int64_t now = GetTimeMs(); /* get now */
- /* how long has it been? */
- int64_t temp = now - i->second.time; /* temp = now - last */
- if (temp > ((int64_t) timeoutMs)) {
- retval = CTR_RxTimeout;
- } else {
- /* our last update was recent enough */
- }
- }
- }
-
- return retval;
-}
-void CtreCanNode::FlushTx(uint32_t arbId)
-{
- int32_t status = 0;
- txJobs_t::iterator iter = _txJobs.find(arbId);
- if(iter != _txJobs.end())
- FRC_NetworkCommunication_CANSessionMux_sendMessage( iter->second.arbId,
- iter->second.toSend,
- iter->second.dlc,
- iter->second.periodMs,
- &status);
-}
-/**
- * Change the transmit period of an already scheduled CAN frame.
- * This keeps the frame payload contents the same without caller having to perform
- * a read-modify-write.
- * @param arbId CAN Frame Arbitration ID. Set BIT31 for 11bit ids, otherwise we use 29bit ids.
- * @param periodMs Period to transmit CAN frame. Pass 0 for one-shot, which also disables that ArbID's preceding periodic transmit.
- * @return true if scheduled job was found and updated, false if there was no preceding job for the specified arbID.
- */
-bool CtreCanNode::ChangeTxPeriod(uint32_t arbId, uint32_t periodMs)
-{
- int32_t status = 0;
- /* lookup the data bytes and period for this message */
- txJobs_t::iterator iter = _txJobs.find(arbId);
- if(iter != _txJobs.end()) {
- /* modify th periodMs */
- iter->second.periodMs = periodMs;
- /* reinsert into scheduler with the same data bytes, only the period changed. */
- FRC_NetworkCommunication_CANSessionMux_sendMessage( iter->second.arbId,
- iter->second.toSend,
- iter->second.dlc,
- iter->second.periodMs,
- &status);
- return true;
- }
- return false;
-}
-
diff --git a/hal/src/main/native/athena/ctre/CtreCanNode.h b/hal/src/main/native/athena/ctre/CtreCanNode.h
deleted file mode 100644
index ce2d6ac..0000000
--- a/hal/src/main/native/athena/ctre/CtreCanNode.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef CtreCanNode_H_
-#define CtreCanNode_H_
-#include "ctre.h" //BIT Defines + Typedefs
-#include <map>
-#include <wpi/mutex.h>
-class CtreCanNode
-{
-public:
- CtreCanNode(UINT8 deviceNumber);
- ~CtreCanNode();
-
- UINT8 GetDeviceNumber()
- {
- return _deviceNumber;
- }
-protected:
-
-
- template <typename T> class txTask{
- public:
- uint32_t arbId;
- T * toSend;
- T * operator -> ()
- {
- return toSend;
- }
- T & operator*()
- {
- return *toSend;
- }
- bool IsEmpty()
- {
- if(toSend == 0)
- return true;
- return false;
- }
- };
- template <typename T> class recMsg{
- public:
- uint32_t arbId;
- uint8_t bytes[8];
- CTR_Code err;
- T * operator -> ()
- {
- return (T *)bytes;
- }
- T & operator*()
- {
- return *(T *)bytes;
- }
- };
- UINT8 _deviceNumber;
- void RegisterRx(uint32_t arbId);
- /**
- * Schedule a CAN Frame for periodic transmit. Assume eight byte DLC and zero value for initial transmission.
- * @param arbId CAN Frame Arbitration ID. Set BIT31 for 11bit ids, otherwise we use 29bit ids.
- * @param periodMs Period to transmit CAN frame. Pass 0 for one-shot, which also disables that ArbID's preceding periodic transmit.
- */
- void RegisterTx(uint32_t arbId, uint32_t periodMs);
- /**
- * Schedule a CAN Frame for periodic transmit.
- * @param arbId CAN Frame Arbitration ID. Set BIT31 for 11bit ids, otherwise we use 29bit ids.
- * @param periodMs Period to transmit CAN frame. Pass 0 for one-shot, which also disables that ArbID's preceding periodic transmit.
- * @param dlc Number of bytes to transmit (0 to 8).
- * @param initialFrame Ptr to the frame data to schedule for transmitting. Passing null will result
- * in defaulting to zero data value.
- */
- void RegisterTx(uint32_t arbId, uint32_t periodMs, uint32_t dlc, const uint8_t * initialFrame);
- void UnregisterTx(uint32_t arbId);
-
- CTR_Code GetRx(uint32_t arbId,uint8_t * dataBytes,uint32_t timeoutMs);
- void FlushTx(uint32_t arbId);
- bool ChangeTxPeriod(uint32_t arbId, uint32_t periodMs);
-
- template<typename T> txTask<T> GetTx(uint32_t arbId)
- {
- txTask<T> retval = {0, nullptr};
- txJobs_t::iterator i = _txJobs.find(arbId);
- if(i != _txJobs.end()){
- retval.arbId = i->second.arbId;
- retval.toSend = (T*)i->second.toSend;
- }
- return retval;
- }
- template<class T> void FlushTx(T & par)
- {
- FlushTx(par.arbId);
- }
-
- template<class T> recMsg<T> GetRx(uint32_t arbId, uint32_t timeoutMs)
- {
- recMsg<T> retval;
- retval.err = GetRx(arbId,retval.bytes, timeoutMs);
- return retval;
- }
-
-private:
-
- class txJob_t {
- public:
- uint32_t arbId;
- uint8_t toSend[8];
- uint32_t periodMs;
- uint8_t dlc;
- };
-
- class rxEvent_t{
- public:
- uint8_t bytes[8];
- int64_t time;
- rxEvent_t()
- {
- bytes[0] = 0;
- bytes[1] = 0;
- bytes[2] = 0;
- bytes[3] = 0;
- bytes[4] = 0;
- bytes[5] = 0;
- bytes[6] = 0;
- bytes[7] = 0;
- }
- };
-
- typedef std::map<uint32_t,txJob_t> txJobs_t;
- txJobs_t _txJobs;
-
- typedef std::map<uint32_t,rxEvent_t> rxRxEvents_t;
- rxRxEvents_t _rxRxEvents;
-
- wpi::mutex _lck;
-};
-#endif
diff --git a/hal/src/main/native/athena/ctre/PCM.cpp b/hal/src/main/native/athena/ctre/PCM.cpp
deleted file mode 100644
index 4fd633f..0000000
--- a/hal/src/main/native/athena/ctre/PCM.cpp
+++ /dev/null
@@ -1,573 +0,0 @@
-#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
-
-#include "PCM.h"
-#include "FRC_NetworkCommunication/CANSessionMux.h"
-/* This can be a constant, as long as nobody needs to update solenoids within
- 1/50 of a second. */
-static const INT32 kCANPeriod = 20;
-
-#define STATUS_1 0x9041400
-#define STATUS_SOL_FAULTS 0x9041440
-#define STATUS_DEBUG 0x9041480
-
-#define EXPECTED_RESPONSE_TIMEOUT_MS (50)
-#define GET_PCM_STATUS() CtreCanNode::recMsg<PcmStatus_t> rx = GetRx<PcmStatus_t> (STATUS_1|GetDeviceNumber(),EXPECTED_RESPONSE_TIMEOUT_MS)
-#define GET_PCM_SOL_FAULTS() CtreCanNode::recMsg<PcmStatusFault_t> rx = GetRx<PcmStatusFault_t> (STATUS_SOL_FAULTS|GetDeviceNumber(),EXPECTED_RESPONSE_TIMEOUT_MS)
-#define GET_PCM_DEBUG() CtreCanNode::recMsg<PcmDebug_t> rx = GetRx<PcmDebug_t> (STATUS_DEBUG|GetDeviceNumber(),EXPECTED_RESPONSE_TIMEOUT_MS)
-
-#define CONTROL_1 0x09041C00 /* PCM_Control */
-#define CONTROL_2 0x09041C40 /* PCM_SupplemControl */
-#define CONTROL_3 0x09041C80 /* PcmControlSetOneShotDur_t */
-
-/* encoder/decoders */
-typedef struct _PcmStatus_t{
- /* Byte 0 */
- unsigned SolenoidBits:8;
- /* Byte 1 */
- unsigned compressorOn:1;
- unsigned stickyFaultFuseTripped:1;
- unsigned stickyFaultCompCurrentTooHigh:1;
- unsigned faultFuseTripped:1;
- unsigned faultCompCurrentTooHigh:1;
- unsigned faultHardwareFailure:1;
- unsigned isCloseloopEnabled:1;
- unsigned pressureSwitchEn:1;
- /* Byte 2*/
- unsigned battVoltage:8;
- /* Byte 3 */
- unsigned solenoidVoltageTop8:8;
- /* Byte 4 */
- unsigned compressorCurrentTop6:6;
- unsigned solenoidVoltageBtm2:2;
- /* Byte 5 */
- unsigned StickyFault_dItooHigh :1;
- unsigned Fault_dItooHigh :1;
- unsigned moduleEnabled:1;
- unsigned closedLoopOutput:1;
- unsigned compressorCurrentBtm4:4;
- /* Byte 6 */
- unsigned tokenSeedTop8:8;
- /* Byte 7 */
- unsigned tokenSeedBtm8:8;
-}PcmStatus_t;
-
-typedef struct _PcmControl_t{
- /* Byte 0 */
- unsigned tokenTop8:8;
- /* Byte 1 */
- unsigned tokenBtm8:8;
- /* Byte 2 */
- unsigned solenoidBits:8;
- /* Byte 3*/
- unsigned reserved:4;
- unsigned closeLoopOutput:1;
- unsigned compressorOn:1;
- unsigned closedLoopEnable:1;
- unsigned clearStickyFaults:1;
- /* Byte 4 */
- unsigned OneShotField_h8:8;
- /* Byte 5 */
- unsigned OneShotField_l8:8;
-}PcmControl_t;
-
-typedef struct _PcmControlSetOneShotDur_t{
- uint8_t sol10MsPerUnit[8];
-}PcmControlSetOneShotDur_t;
-
-typedef struct _PcmStatusFault_t{
- /* Byte 0 */
- unsigned SolenoidBlacklist:8;
- /* Byte 1 */
- unsigned reserved_bit0 :1;
- unsigned reserved_bit1 :1;
- unsigned reserved_bit2 :1;
- unsigned reserved_bit3 :1;
- unsigned StickyFault_CompNoCurrent :1;
- unsigned Fault_CompNoCurrent :1;
- unsigned StickyFault_SolenoidJumper :1;
- unsigned Fault_SolenoidJumper :1;
-}PcmStatusFault_t;
-
-typedef struct _PcmDebug_t{
- unsigned tokFailsTop8:8;
- unsigned tokFailsBtm8:8;
- unsigned lastFailedTokTop8:8;
- unsigned lastFailedTokBtm8:8;
- unsigned tokSuccessTop8:8;
- unsigned tokSuccessBtm8:8;
-}PcmDebug_t;
-
-
-/* PCM Constructor - Clears all vars, establishes default settings, starts PCM background process
- *
- * @Return - void
- *
- * @Param - deviceNumber - Device ID of PCM to be controlled
- */
-PCM::PCM(UINT8 deviceNumber): CtreCanNode(deviceNumber)
-{
- RegisterRx(STATUS_1 | deviceNumber );
- RegisterRx(STATUS_SOL_FAULTS | deviceNumber );
- RegisterRx(STATUS_DEBUG | deviceNumber );
- RegisterTx(CONTROL_1 | deviceNumber, kCANPeriod);
- /* enable close loop */
- SetClosedLoopControl(1);
-}
-/* PCM D'tor
- */
-PCM::~PCM()
-{
-
-}
-
-/* Set PCM solenoid state
- *
- * @Return - CTR_Code - Error code (if any) for setting solenoid
- *
- * @Param - idx - ID of solenoid (0-7)
- * @Param - en - Enable / Disable identified solenoid
- */
-CTR_Code PCM::SetSolenoid(unsigned char idx, bool en)
-{
- CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());
- if(toFill.IsEmpty())return CTR_UnexpectedArbId;
- if (en)
- toFill->solenoidBits |= (1ul << (idx));
- else
- toFill->solenoidBits &= ~(1ul << (idx));
- FlushTx(toFill);
- return CTR_OKAY;
-}
-
-/* Set all PCM solenoid states
- *
- * @Return - CTR_Code - Error code (if any) for setting solenoids
- * @Param - state Bitfield to set all solenoids to
- */
-CTR_Code PCM::SetAllSolenoids(UINT8 state) {
- CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());
- if(toFill.IsEmpty())return CTR_UnexpectedArbId;
- toFill->solenoidBits = state;
- FlushTx(toFill);
- return CTR_OKAY;
-}
-
-/* Clears PCM sticky faults (indicators of past faults
- *
- * @Return - CTR_Code - Error code (if any) for setting solenoid
- *
- * @Param - clr - Clear / do not clear faults
- */
-CTR_Code PCM::ClearStickyFaults()
-{
- int32_t status = 0;
- uint8_t pcmSupplemControl[] = { 0, 0, 0, 0x80 }; /* only bit set is ClearStickyFaults */
- FRC_NetworkCommunication_CANSessionMux_sendMessage(CONTROL_2 | GetDeviceNumber(), pcmSupplemControl, sizeof(pcmSupplemControl), 0, &status);
- if(status)
- return CTR_TxFailed;
- return CTR_OKAY;
-}
-
-/* Enables PCM Closed Loop Control of Compressor via pressure switch
- *
- * @Return - CTR_Code - Error code (if any) for setting solenoid
- *
- * @Param - en - Enable / Disable Closed Loop Control
- */
-CTR_Code PCM::SetClosedLoopControl(bool en)
-{
- CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());
- if(toFill.IsEmpty())return CTR_UnexpectedArbId;
- toFill->closedLoopEnable = en;
- FlushTx(toFill);
- return CTR_OKAY;
-}
-/* Get solenoid Blacklist status
- * @Return - CTR_Code - Error code (if any)
- * @Param - idx - ID of solenoid [0,7] to fire one shot pulse.
- */
-CTR_Code PCM::FireOneShotSolenoid(UINT8 idx)
-{
- CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());
- if(toFill.IsEmpty())return CTR_UnexpectedArbId;
- /* grab field as it is now */
- uint16_t oneShotField;
- oneShotField = toFill->OneShotField_h8;
- oneShotField <<= 8;
- oneShotField |= toFill->OneShotField_l8;
- /* get the caller's channel */
- uint16_t shift = 2*idx;
- uint16_t mask = 3; /* two bits wide */
- uint8_t chBits = (oneShotField >> shift) & mask;
- /* flip it */
- chBits = (chBits)%3 + 1;
- /* clear out 2bits for this channel*/
- oneShotField &= ~(mask << shift);
- /* put new field in */
- oneShotField |= chBits << shift;
- /* apply field as it is now */
- toFill->OneShotField_h8 = oneShotField >> 8;
- toFill->OneShotField_l8 = oneShotField;
- FlushTx(toFill);
- return CTR_OKAY;
-}
-/* Configure the pulse width of a solenoid channel for one-shot pulse.
- * Preprogrammed pulsewidth is 10ms resolution and can be between 10ms and
- * 2.55s.
- *
- * @Return - CTR_Code - Error code (if any)
- * @Param - idx - ID of solenoid [0,7] to configure.
- * @Param - durMs - pulse width in ms.
- */
-CTR_Code PCM::SetOneShotDurationMs(UINT8 idx,uint32_t durMs)
-{
- /* sanity check caller's param */
- if(idx > 7)
- return CTR_InvalidParamValue;
- /* get latest tx frame */
- CtreCanNode::txTask<PcmControlSetOneShotDur_t> toFill = GetTx<PcmControlSetOneShotDur_t>(CONTROL_3 | GetDeviceNumber());
- if(toFill.IsEmpty()){
- /* only send this out if caller wants to do one-shots */
- RegisterTx(CONTROL_3 | _deviceNumber, kCANPeriod);
- /* grab it */
- toFill = GetTx<PcmControlSetOneShotDur_t>(CONTROL_3 | GetDeviceNumber());
- }
- toFill->sol10MsPerUnit[idx] = std::min(durMs/10,(uint32_t)0xFF);
- /* apply the new data bytes */
- FlushTx(toFill);
- return CTR_OKAY;
-}
-
-/* Get solenoid state
- *
- * @Return - True/False - True if solenoid enabled, false otherwise
- *
- * @Param - idx - ID of solenoid (0-7) to return status of
- */
-CTR_Code PCM::GetSolenoid(UINT8 idx, bool &status)
-{
- GET_PCM_STATUS();
- status = (rx->SolenoidBits & (1ul<<(idx)) ) ? 1 : 0;
- return rx.err;
-}
-
-/* Get solenoid state for all solenoids on the PCM
- *
- * @Return - Bitfield of solenoid states
- */
-CTR_Code PCM::GetAllSolenoids(UINT8 &status)
-{
- GET_PCM_STATUS();
- status = rx->SolenoidBits;
- return rx.err;
-}
-
-/* Get pressure switch state
- *
- * @Return - True/False - True if pressure adequate, false if low
- */
-CTR_Code PCM::GetPressure(bool &status)
-{
- GET_PCM_STATUS();
- status = (rx->pressureSwitchEn ) ? 1 : 0;
- return rx.err;
-}
-
-/* Get compressor state
- *
- * @Return - True/False - True if enabled, false if otherwise
- */
-CTR_Code PCM::GetCompressor(bool &status)
-{
- GET_PCM_STATUS();
- status = (rx->compressorOn);
- return rx.err;
-}
-
-/* Get closed loop control state
- *
- * @Return - True/False - True if closed loop enabled, false if otherwise
- */
-CTR_Code PCM::GetClosedLoopControl(bool &status)
-{
- GET_PCM_STATUS();
- status = (rx->isCloseloopEnabled);
- return rx.err;
-}
-
-/* Get compressor current draw
- *
- * @Return - Amperes - Compressor current
- */
-CTR_Code PCM::GetCompressorCurrent(float &status)
-{
- GET_PCM_STATUS();
- uint32_t temp =(rx->compressorCurrentTop6);
- temp <<= 4;
- temp |= rx->compressorCurrentBtm4;
- status = temp * 0.03125; /* 5.5 fixed pt value in Amps */
- return rx.err;
-}
-
-/* Get voltage across solenoid rail
- *
- * @Return - Volts - Voltage across solenoid rail
- */
-CTR_Code PCM::GetSolenoidVoltage(float &status)
-{
- GET_PCM_STATUS();
- uint32_t raw =(rx->solenoidVoltageTop8);
- raw <<= 2;
- raw |= rx->solenoidVoltageBtm2;
- status = (double) raw * 0.03125; /* 5.5 fixed pt value in Volts */
- return rx.err;
-}
-
-/* Get hardware fault value
- *
- * @Return - True/False - True if hardware failure detected, false if otherwise
- */
-CTR_Code PCM::GetHardwareFault(bool &status)
-{
- GET_PCM_STATUS();
- status = rx->faultHardwareFailure;
- return rx.err;
-}
-
-/* Get compressor fault value
- *
- * @Return - True/False - True if shorted compressor detected, false if otherwise
- */
-CTR_Code PCM::GetCompressorCurrentTooHighFault(bool &status)
-{
- GET_PCM_STATUS();
- status = rx->faultCompCurrentTooHigh;
- return rx.err;
-}
-CTR_Code PCM::GetCompressorShortedStickyFault(bool &status)
-{
- GET_PCM_STATUS();
- status = rx->StickyFault_dItooHigh;
- return rx.err;
-}
-CTR_Code PCM::GetCompressorShortedFault(bool &status)
-{
- GET_PCM_STATUS();
- status = rx->Fault_dItooHigh;
- return rx.err;
-}
-CTR_Code PCM::GetCompressorNotConnectedStickyFault(bool &status)
-{
- GET_PCM_SOL_FAULTS();
- status = rx->StickyFault_CompNoCurrent;
- return rx.err;
-}
-CTR_Code PCM::GetCompressorNotConnectedFault(bool &status)
-{
- GET_PCM_SOL_FAULTS();
- status = rx->Fault_CompNoCurrent;
- return rx.err;
-}
-
-/* Get solenoid fault value
- *
- * @Return - True/False - True if shorted solenoid detected, false if otherwise
- */
-CTR_Code PCM::GetSolenoidFault(bool &status)
-{
- GET_PCM_STATUS();
- status = rx->faultFuseTripped;
- return rx.err;
-}
-
-/* Get compressor sticky fault value
- *
- * @Return - True/False - True if solenoid had previously been shorted
- * (and sticky fault was not cleared), false if otherwise
- */
-CTR_Code PCM::GetCompressorCurrentTooHighStickyFault(bool &status)
-{
- GET_PCM_STATUS();
- status = rx->stickyFaultCompCurrentTooHigh;
- return rx.err;
-}
-
-/* Get solenoid sticky fault value
- *
- * @Return - True/False - True if compressor had previously been shorted
- * (and sticky fault was not cleared), false if otherwise
- */
-CTR_Code PCM::GetSolenoidStickyFault(bool &status)
-{
- GET_PCM_STATUS();
- status = rx->stickyFaultFuseTripped;
- return rx.err;
-}
-/* Get battery voltage
- *
- * @Return - Volts - Voltage across PCM power ports
- */
-CTR_Code PCM::GetBatteryVoltage(float &status)
-{
- GET_PCM_STATUS();
- status = (float)rx->battVoltage * 0.05 + 4.0; /* 50mV per unit plus 4V. */
- return rx.err;
-}
-/* Return status of module enable/disable
- *
- * @Return - bool - Returns TRUE if PCM is enabled, FALSE if disabled
- */
-CTR_Code PCM::isModuleEnabled(bool &status)
-{
- GET_PCM_STATUS();
- status = rx->moduleEnabled;
- return rx.err;
-}
-/* Get number of total failed PCM Control Frame
- *
- * @Return - Failed Control Frames - Number of failed control frames (tokenization fails)
- *
- * @WARNING - Return only valid if [SeekDebugFrames] is enabled
- * See function SeekDebugFrames
- * See function EnableSeekDebugFrames
- */
-CTR_Code PCM::GetNumberOfFailedControlFrames(UINT16 &status)
-{
- GET_PCM_DEBUG();
- status = rx->tokFailsTop8;
- status <<= 8;
- status |= rx->tokFailsBtm8;
- return rx.err;
-}
-/* Get raw Solenoid Blacklist
- *
- * @Return - BINARY - Raw binary breakdown of Solenoid Blacklist
- * BIT7 = Solenoid 1, BIT6 = Solenoid 2, etc.
- *
- * @WARNING - Return only valid if [SeekStatusFaultFrames] is enabled
- * See function SeekStatusFaultFrames
- * See function EnableSeekStatusFaultFrames
- */
-CTR_Code PCM::GetSolenoidBlackList(UINT8 &status)
-{
- GET_PCM_SOL_FAULTS();
- status = rx->SolenoidBlacklist;
- return rx.err;
-}
-/* Get solenoid Blacklist status
- * - Blacklisted solenoids cannot be enabled until PCM is power cycled
- *
- * @Return - True/False - True if Solenoid is blacklisted, false if otherwise
- *
- * @Param - idx - ID of solenoid [0,7]
- *
- * @WARNING - Return only valid if [SeekStatusFaultFrames] is enabled
- * See function SeekStatusFaultFrames
- * See function EnableSeekStatusFaultFrames
- */
-CTR_Code PCM::IsSolenoidBlacklisted(UINT8 idx, bool &status)
-{
- GET_PCM_SOL_FAULTS();
- status = (rx->SolenoidBlacklist & (1ul<<(idx)) )? 1 : 0;
- return rx.err;
-}
-//------------------ C interface --------------------------------------------//
-extern "C" {
- void * c_PCM_Init(void) {
- return new PCM();
- }
- CTR_Code c_SetSolenoid(void * handle, unsigned char idx, INT8 param) {
- return ((PCM*) handle)->SetSolenoid(idx, param);
- }
- CTR_Code c_SetAllSolenoids(void * handle, UINT8 state) {
- return ((PCM*) handle)->SetAllSolenoids(state);
- }
- CTR_Code c_SetClosedLoopControl(void * handle, INT8 param) {
- return ((PCM*) handle)->SetClosedLoopControl(param);
- }
- CTR_Code c_ClearStickyFaults(void * handle, INT8 param) {
- return ((PCM*) handle)->ClearStickyFaults();
- }
- CTR_Code c_GetSolenoid(void * handle, UINT8 idx, INT8 * status) {
- bool bstatus;
- CTR_Code retval = ((PCM*) handle)->GetSolenoid(idx, bstatus);
- *status = bstatus;
- return retval;
- }
- CTR_Code c_GetAllSolenoids(void * handle, UINT8 * status) {
- return ((PCM*) handle)->GetAllSolenoids(*status);
- }
- CTR_Code c_GetPressure(void * handle, INT8 * status) {
- bool bstatus;
- CTR_Code retval = ((PCM*) handle)->GetPressure(bstatus);
- *status = bstatus;
- return retval;
- }
- CTR_Code c_GetCompressor(void * handle, INT8 * status) {
- bool bstatus;
- CTR_Code retval = ((PCM*) handle)->GetCompressor(bstatus);
- *status = bstatus;
- return retval;
- }
- CTR_Code c_GetClosedLoopControl(void * handle, INT8 * status) {
- bool bstatus;
- CTR_Code retval = ((PCM*) handle)->GetClosedLoopControl(bstatus);
- *status = bstatus;
- return retval;
- }
- CTR_Code c_GetCompressorCurrent(void * handle, float * status) {
- CTR_Code retval = ((PCM*) handle)->GetCompressorCurrent(*status);
- return retval;
- }
- CTR_Code c_GetSolenoidVoltage(void * handle, float*status) {
- return ((PCM*) handle)->GetSolenoidVoltage(*status);
- }
- CTR_Code c_GetHardwareFault(void * handle, INT8*status) {
- bool bstatus;
- CTR_Code retval = ((PCM*) handle)->GetHardwareFault(bstatus);
- *status = bstatus;
- return retval;
- }
- CTR_Code c_GetCompressorFault(void * handle, INT8*status) {
- bool bstatus;
- CTR_Code retval = ((PCM*) handle)->GetCompressorCurrentTooHighFault(bstatus);
- *status = bstatus;
- return retval;
- }
- CTR_Code c_GetSolenoidFault(void * handle, INT8*status) {
- bool bstatus;
- CTR_Code retval = ((PCM*) handle)->GetSolenoidFault(bstatus);
- *status = bstatus;
- return retval;
- }
- CTR_Code c_GetCompressorStickyFault(void * handle, INT8*status) {
- bool bstatus;
- CTR_Code retval = ((PCM*) handle)->GetCompressorCurrentTooHighStickyFault(bstatus);
- *status = bstatus;
- return retval;
- }
- CTR_Code c_GetSolenoidStickyFault(void * handle, INT8*status) {
- bool bstatus;
- CTR_Code retval = ((PCM*) handle)->GetSolenoidStickyFault(bstatus);
- *status = bstatus;
- return retval;
- }
- CTR_Code c_GetBatteryVoltage(void * handle, float*status) {
- CTR_Code retval = ((PCM*) handle)->GetBatteryVoltage(*status);
- return retval;
- }
- void c_SetDeviceNumber_PCM(void * handle, UINT8 deviceNumber) {
- }
- CTR_Code c_GetNumberOfFailedControlFrames(void * handle, UINT16*status) {
- return ((PCM*) handle)->GetNumberOfFailedControlFrames(*status);
- }
- CTR_Code c_GetSolenoidBlackList(void * handle, UINT8 *status) {
- return ((PCM*) handle)->GetSolenoidBlackList(*status);
- }
- CTR_Code c_IsSolenoidBlacklisted(void * handle, UINT8 idx, INT8*status) {
- bool bstatus;
- CTR_Code retval = ((PCM*) handle)->IsSolenoidBlacklisted(idx, bstatus);
- *status = bstatus;
- return retval;
- }
-}
diff --git a/hal/src/main/native/athena/ctre/PCM.h b/hal/src/main/native/athena/ctre/PCM.h
deleted file mode 100644
index 4923202..0000000
--- a/hal/src/main/native/athena/ctre/PCM.h
+++ /dev/null
@@ -1,226 +0,0 @@
-#ifndef PCM_H_
-#define PCM_H_
-#include "ctre.h" //BIT Defines + Typedefs
-#include "CtreCanNode.h"
-class PCM : public CtreCanNode
-{
-public:
- PCM(UINT8 deviceNumber=0);
- ~PCM();
-
- /* Set PCM solenoid state
- *
- * @Return - CTR_Code - Error code (if any) for setting solenoid
- * @Param - idx - ID of solenoid (0-7)
- * @Param - en - Enable / Disable identified solenoid
- */
- CTR_Code SetSolenoid(unsigned char idx, bool en);
-
- /* Set all PCM solenoid states
- *
- * @Return - CTR_Code - Error code (if any) for setting solenoids
- * @Param - state Bitfield to set all solenoids to
- */
- CTR_Code SetAllSolenoids(UINT8 state);
-
- /* Enables PCM Closed Loop Control of Compressor via pressure switch
- * @Return - CTR_Code - Error code (if any) for setting solenoid
- * @Param - en - Enable / Disable Closed Loop Control
- */
- CTR_Code SetClosedLoopControl(bool en);
-
- /* Clears PCM sticky faults (indicators of past faults
- * @Return - CTR_Code - Error code (if any) for setting solenoid
- */
- CTR_Code ClearStickyFaults();
-
- /* Get solenoid state
- *
- * @Return - CTR_Code - Error code (if any)
- * @Param - idx - ID of solenoid (0-7) to return if solenoid is on.
- * @Param - status - true if solenoid enabled, false otherwise
- */
- CTR_Code GetSolenoid(UINT8 idx, bool &status);
-
- /* Get state of all solenoids
- *
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - bitfield of solenoid states
- */
- CTR_Code GetAllSolenoids(UINT8 &status);
-
- /* Get pressure switch state
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - True if pressure adequate, false if low
- */
- CTR_Code GetPressure(bool &status);
-
- /* Get compressor state
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - True if compress output is on, false if otherwise
- */
- CTR_Code GetCompressor(bool &status);
-
- /* Get closed loop control state
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - True if closed loop enabled, false if otherwise
- */
- CTR_Code GetClosedLoopControl(bool &status);
-
- /* Get compressor current draw
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - Compressor current returned in Amperes (A)
- */
- CTR_Code GetCompressorCurrent(float &status);
-
- /* Get voltage across solenoid rail
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - Voltage across solenoid rail in Volts (V)
- */
- CTR_Code GetSolenoidVoltage(float &status);
-
- /* Get hardware fault value
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - True if hardware failure detected, false if otherwise
- */
- CTR_Code GetHardwareFault(bool &status);
-
- /* Get compressor fault value
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - True if abnormally high compressor current detected, false if otherwise
- */
- CTR_Code GetCompressorCurrentTooHighFault(bool &status);
-
- /* Get solenoid fault value
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - True if shorted solenoid detected, false if otherwise
- */
- CTR_Code GetSolenoidFault(bool &status);
-
- /* Get compressor sticky fault value
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - True if solenoid had previously been shorted
- * (and sticky fault was not cleared), false if otherwise
- */
- CTR_Code GetCompressorCurrentTooHighStickyFault(bool &status);
- /* Get compressor shorted sticky fault value
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - True if compressor output is shorted, false if otherwise
- */
- CTR_Code GetCompressorShortedStickyFault(bool &status);
- /* Get compressor shorted fault value
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - True if compressor output is shorted, false if otherwise
- */
- CTR_Code GetCompressorShortedFault(bool &status);
- /* Get compressor is not connected sticky fault value
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - True if compressor current is too low,
- * indicating compressor is not connected, false if otherwise
- */
- CTR_Code GetCompressorNotConnectedStickyFault(bool &status);
- /* Get compressor is not connected fault value
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - True if compressor current is too low,
- * indicating compressor is not connected, false if otherwise
- */
- CTR_Code GetCompressorNotConnectedFault(bool &status);
-
- /* Get solenoid sticky fault value
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - True if compressor had previously been shorted
- * (and sticky fault was not cleared), false if otherwise
- */
- CTR_Code GetSolenoidStickyFault(bool &status);
-
- /* Get battery voltage
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - Voltage across PCM power ports in Volts (V)
- */
- CTR_Code GetBatteryVoltage(float &status);
-
- /* Set PCM Device Number and according CAN frame IDs
- * @Return - void
- * @Param - deviceNumber - Device number of PCM to control
- */
- void SetDeviceNumber(UINT8 deviceNumber);
- /* Get number of total failed PCM Control Frame
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - Number of failed control frames (tokenization fails)
- * @WARNING - Return only valid if [SeekDebugFrames] is enabled
- * See function SeekDebugFrames
- * See function EnableSeekDebugFrames
- */
- CTR_Code GetNumberOfFailedControlFrames(UINT16 &status);
-
- /* Get raw Solenoid Blacklist
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - Raw binary breakdown of Solenoid Blacklist
- * BIT7 = Solenoid 1, BIT6 = Solenoid 2, etc.
- * @WARNING - Return only valid if [SeekStatusFaultFrames] is enabled
- * See function SeekStatusFaultFrames
- * See function EnableSeekStatusFaultFrames
- */
- CTR_Code GetSolenoidBlackList(UINT8 &status);
-
- /* Get solenoid Blacklist status
- * - Blacklisted solenoids cannot be enabled until PCM is power cycled
- * @Return - CTR_Code - Error code (if any)
- * @Param - idx - ID of solenoid [0,7]
- * @Param - status - True if Solenoid is blacklisted, false if otherwise
- * @WARNING - Return only valid if [SeekStatusFaultFrames] is enabled
- * See function SeekStatusFaultFrames
- * See function EnableSeekStatusFaultFrames
- */
- CTR_Code IsSolenoidBlacklisted(UINT8 idx, bool &status);
-
- /* Return status of module enable/disable
- * @Return - CTR_Code - Error code (if any)
- * @Param - status - Returns TRUE if PCM is enabled, FALSE if disabled
- */
- CTR_Code isModuleEnabled(bool &status);
-
- /* Get solenoid Blacklist status
- * @Return - CTR_Code - Error code (if any)
- * @Param - idx - ID of solenoid [0,7] to fire one shot pulse.
- */
- CTR_Code FireOneShotSolenoid(UINT8 idx);
-
- /* Configure the pulse width of a solenoid channel for one-shot pulse.
- * Preprogrammed pulsewidth is 10ms resolute and can be between 20ms and 5.1s.
- * @Return - CTR_Code - Error code (if any)
- * @Param - idx - ID of solenoid [0,7] to configure.
- * @Param - durMs - pulse width in ms.
- */
- CTR_Code SetOneShotDurationMs(UINT8 idx,uint32_t durMs);
-
-};
-//------------------ C interface --------------------------------------------//
-extern "C" {
- void * c_PCM_Init(void);
- CTR_Code c_SetSolenoid(void * handle,unsigned char idx,INT8 param);
- CTR_Code c_SetAllSolenoids(void * handle,UINT8 state);
- CTR_Code c_SetClosedLoopControl(void * handle,INT8 param);
- CTR_Code c_ClearStickyFaults(void * handle,INT8 param);
- CTR_Code c_GetSolenoid(void * handle,UINT8 idx,INT8 * status);
- CTR_Code c_GetAllSolenoids(void * handle,UINT8 * status);
- CTR_Code c_GetPressure(void * handle,INT8 * status);
- CTR_Code c_GetCompressor(void * handle,INT8 * status);
- CTR_Code c_GetClosedLoopControl(void * handle,INT8 * status);
- CTR_Code c_GetCompressorCurrent(void * handle,float * status);
- CTR_Code c_GetSolenoidVoltage(void * handle,float*status);
- CTR_Code c_GetHardwareFault(void * handle,INT8*status);
- CTR_Code c_GetCompressorFault(void * handle,INT8*status);
- CTR_Code c_GetSolenoidFault(void * handle,INT8*status);
- CTR_Code c_GetCompressorStickyFault(void * handle,INT8*status);
- CTR_Code c_GetSolenoidStickyFault(void * handle,INT8*status);
- CTR_Code c_GetBatteryVoltage(void * handle,float*status);
- void c_SetDeviceNumber_PCM(void * handle,UINT8 deviceNumber);
- void c_EnableSeekStatusFrames(void * handle,INT8 enable);
- void c_EnableSeekStatusFaultFrames(void * handle,INT8 enable);
- void c_EnableSeekDebugFrames(void * handle,INT8 enable);
- CTR_Code c_GetNumberOfFailedControlFrames(void * handle,UINT16*status);
- CTR_Code c_GetSolenoidBlackList(void * handle,UINT8 *status);
- CTR_Code c_IsSolenoidBlacklisted(void * handle,UINT8 idx,INT8*status);
-}
-#endif
diff --git a/hal/src/main/native/athena/ctre/ctre.h b/hal/src/main/native/athena/ctre/ctre.h
deleted file mode 100644
index 90d33c1..0000000
--- a/hal/src/main/native/athena/ctre/ctre.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * @file ctre.h
- * Common header for all CTRE HAL modules.
- */
-#ifndef CTRE_H
-#define CTRE_H
-
-//Bit Defines
-#define BIT0 0x01
-#define BIT1 0x02
-#define BIT2 0x04
-#define BIT3 0x08
-#define BIT4 0x10
-#define BIT5 0x20
-#define BIT6 0x40
-#define BIT7 0x80
-#define BIT8 0x0100
-#define BIT9 0x0200
-#define BIT10 0x0400
-#define BIT11 0x0800
-#define BIT12 0x1000
-#define BIT13 0x2000
-#define BIT14 0x4000
-#define BIT15 0x8000
-
-//Signed
-typedef signed char INT8;
-typedef signed short INT16;
-typedef signed int INT32;
-typedef signed long long INT64;
-
-//Unsigned
-typedef unsigned char UINT8;
-typedef unsigned short UINT16;
-typedef unsigned int UINT32;
-typedef unsigned long long UINT64;
-
-//Other
-typedef unsigned char UCHAR;
-typedef unsigned short USHORT;
-typedef unsigned int UINT;
-typedef unsigned long ULONG;
-
-typedef enum {
- CTR_OKAY, //!< No Error - Function executed as expected
- CTR_RxTimeout, //!< CAN frame has not been received within specified period of time.
- CTR_TxTimeout, //!< Not used.
- CTR_InvalidParamValue, //!< Caller passed an invalid param
- CTR_UnexpectedArbId, //!< Specified CAN Id is invalid.
- CTR_TxFailed, //!< Could not transmit the CAN frame.
- CTR_SigNotUpdated, //!< Have not received an value response for signal.
- CTR_BufferFull, //!< Caller attempted to insert data into a buffer that is full.
-}CTR_Code;
-
-#endif /* CTRE_H */
diff --git a/hal/src/main/native/athena/mockdata/AccelerometerData.cpp b/hal/src/main/native/athena/mockdata/AccelerometerData.cpp
index 2baaf78..e097a24 100644
--- a/hal/src/main/native/athena/mockdata/AccelerometerData.cpp
+++ b/hal/src/main/native/athena/mockdata/AccelerometerData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/AccelerometerData.h"
diff --git a/hal/src/main/native/athena/mockdata/AddressableLEDData.cpp b/hal/src/main/native/athena/mockdata/AddressableLEDData.cpp
index d718789..a1d7011 100644
--- a/hal/src/main/native/athena/mockdata/AddressableLEDData.cpp
+++ b/hal/src/main/native/athena/mockdata/AddressableLEDData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/AddressableLEDData.h"
@@ -11,7 +8,9 @@
extern "C" {
-int32_t HALSIM_FindAddressableLEDForChannel(int32_t channel) { return 0; }
+int32_t HALSIM_FindAddressableLEDForChannel(int32_t channel) {
+ return 0;
+}
void HALSIM_ResetAddressableLEDData(int32_t index) {}
diff --git a/hal/src/main/native/athena/mockdata/AnalogGyroData.cpp b/hal/src/main/native/athena/mockdata/AnalogGyroData.cpp
index d91ce27..b4ff695 100644
--- a/hal/src/main/native/athena/mockdata/AnalogGyroData.cpp
+++ b/hal/src/main/native/athena/mockdata/AnalogGyroData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/AnalogGyroData.h"
diff --git a/hal/src/main/native/athena/mockdata/AnalogInData.cpp b/hal/src/main/native/athena/mockdata/AnalogInData.cpp
index 4288538..30ac795 100644
--- a/hal/src/main/native/athena/mockdata/AnalogInData.cpp
+++ b/hal/src/main/native/athena/mockdata/AnalogInData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/AnalogInData.h"
@@ -12,7 +9,9 @@
extern "C" {
void HALSIM_ResetAnalogInData(int32_t index) {}
-HAL_SimDeviceHandle HALSIM_GetAnalogInSimDevice(int32_t index) { return 0; }
+HAL_SimDeviceHandle HALSIM_GetAnalogInSimDevice(int32_t index) {
+ return 0;
+}
#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, AnalogIn##CAPINAME, RETURN)
diff --git a/hal/src/main/native/athena/mockdata/AnalogOutData.cpp b/hal/src/main/native/athena/mockdata/AnalogOutData.cpp
index f05b0be..e6da2aa 100644
--- a/hal/src/main/native/athena/mockdata/AnalogOutData.cpp
+++ b/hal/src/main/native/athena/mockdata/AnalogOutData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/AnalogOutData.h"
diff --git a/hal/src/main/native/athena/mockdata/AnalogTriggerData.cpp b/hal/src/main/native/athena/mockdata/AnalogTriggerData.cpp
index 7781cf2..af8d7cc 100644
--- a/hal/src/main/native/athena/mockdata/AnalogTriggerData.cpp
+++ b/hal/src/main/native/athena/mockdata/AnalogTriggerData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/AnalogTriggerData.h"
@@ -11,7 +8,9 @@
extern "C" {
-int32_t HALSIM_FindAnalogTriggerForChannel(int32_t channel) { return 0; }
+int32_t HALSIM_FindAnalogTriggerForChannel(int32_t channel) {
+ return 0;
+}
void HALSIM_ResetAnalogTriggerData(int32_t index) {}
diff --git a/hal/src/main/native/athena/mockdata/CTREPCMData.cpp b/hal/src/main/native/athena/mockdata/CTREPCMData.cpp
new file mode 100644
index 0000000..fc9edfe
--- /dev/null
+++ b/hal/src/main/native/athena/mockdata/CTREPCMData.cpp
@@ -0,0 +1,38 @@
+// 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/simulation/CTREPCMData.h"
+
+#include "hal/simulation/SimDataValue.h"
+
+extern "C" {
+void HALSIM_ResetCTREPCMData(int32_t index) {}
+
+#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
+ HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, CTREPCM##CAPINAME, RETURN)
+
+HAL_SIMDATAVALUE_STUB_CAPI_CHANNEL(HAL_Bool, HALSIM, CTREPCMSolenoidOutput,
+ false)
+DEFINE_CAPI(HAL_Bool, Initialized, false)
+DEFINE_CAPI(HAL_Bool, CompressorOn, false)
+DEFINE_CAPI(HAL_Bool, ClosedLoopEnabled, false)
+DEFINE_CAPI(HAL_Bool, PressureSwitch, false)
+DEFINE_CAPI(double, CompressorCurrent, 0)
+
+void HALSIM_GetCTREPCMAllSolenoids(int32_t index, uint8_t* values) {
+ *values = 0;
+}
+
+void HALSIM_SetCTREPCMAllSolenoids(int32_t index, uint8_t values) {}
+
+void HALSIM_RegisterCTREPCMAllNonSolenoidCallbacks(int32_t index,
+ HAL_NotifyCallback callback,
+ void* param,
+ HAL_Bool initialNotify) {}
+
+void HALSIM_RegisterCTREPCMAllSolenoidCallbacks(int32_t index, int32_t channel,
+ HAL_NotifyCallback callback,
+ void* param,
+ HAL_Bool initialNotify) {}
+} // extern "C"
diff --git a/hal/src/main/native/athena/mockdata/CanDataInternal.cpp b/hal/src/main/native/athena/mockdata/CanDataInternal.cpp
index 69debf0..be2fbc0 100644
--- a/hal/src/main/native/athena/mockdata/CanDataInternal.cpp
+++ b/hal/src/main/native/athena/mockdata/CanDataInternal.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/CanData.h"
#include "hal/simulation/SimDataValue.h"
diff --git a/hal/src/main/native/athena/mockdata/DIOData.cpp b/hal/src/main/native/athena/mockdata/DIOData.cpp
index a06855d..392c31b 100644
--- a/hal/src/main/native/athena/mockdata/DIOData.cpp
+++ b/hal/src/main/native/athena/mockdata/DIOData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/DIOData.h"
@@ -12,7 +9,9 @@
extern "C" {
void HALSIM_ResetDIOData(int32_t index) {}
-HAL_SimDeviceHandle HALSIM_GetDIOSimDevice(int32_t index) { return 0; }
+HAL_SimDeviceHandle HALSIM_GetDIOSimDevice(int32_t index) {
+ return 0;
+}
#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, DIO##CAPINAME, RETURN)
diff --git a/hal/src/main/native/athena/mockdata/DigitalPWMData.cpp b/hal/src/main/native/athena/mockdata/DigitalPWMData.cpp
index bcbe370..c3f5d31 100644
--- a/hal/src/main/native/athena/mockdata/DigitalPWMData.cpp
+++ b/hal/src/main/native/athena/mockdata/DigitalPWMData.cpp
@@ -1,16 +1,15 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/DigitalPWMData.h"
#include "hal/simulation/SimDataValue.h"
extern "C" {
-int32_t HALSIM_FindDigitalPWMForChannel(int32_t channel) { return 0; }
+int32_t HALSIM_FindDigitalPWMForChannel(int32_t channel) {
+ return 0;
+}
void HALSIM_ResetDigitalPWMData(int32_t index) {}
diff --git a/hal/src/main/native/athena/mockdata/DriverStationData.cpp b/hal/src/main/native/athena/mockdata/DriverStationData.cpp
index b4695ba..ba519fc 100644
--- a/hal/src/main/native/athena/mockdata/DriverStationData.cpp
+++ b/hal/src/main/native/athena/mockdata/DriverStationData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/DriverStationData.h"
diff --git a/hal/src/main/native/athena/mockdata/DutyCycleData.cpp b/hal/src/main/native/athena/mockdata/DutyCycleData.cpp
index 8d3cd61..d63e27e 100644
--- a/hal/src/main/native/athena/mockdata/DutyCycleData.cpp
+++ b/hal/src/main/native/athena/mockdata/DutyCycleData.cpp
@@ -1,22 +1,25 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/DutyCycleData.h"
#include "hal/simulation/SimDataValue.h"
extern "C" {
-int32_t HALSIM_FindDutyCycleForChannel(int32_t channel) { return 0; }
+int32_t HALSIM_FindDutyCycleForChannel(int32_t channel) {
+ return 0;
+}
void HALSIM_ResetDutyCycleData(int32_t index) {}
-int32_t HALSIM_GetDutyCycleDigitalChannel(int32_t index) { return 0; }
+int32_t HALSIM_GetDutyCycleDigitalChannel(int32_t index) {
+ return 0;
+}
-HAL_SimDeviceHandle HALSIM_GetDutyCycleSimDevice(int32_t index) { return 0; }
+HAL_SimDeviceHandle HALSIM_GetDutyCycleSimDevice(int32_t index) {
+ return 0;
+}
#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, DutyCycle##CAPINAME, RETURN)
diff --git a/hal/src/main/native/athena/mockdata/EncoderData.cpp b/hal/src/main/native/athena/mockdata/EncoderData.cpp
index 87a7385..4b07b31 100644
--- a/hal/src/main/native/athena/mockdata/EncoderData.cpp
+++ b/hal/src/main/native/athena/mockdata/EncoderData.cpp
@@ -1,24 +1,29 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/EncoderData.h"
#include "hal/simulation/SimDataValue.h"
extern "C" {
-int32_t HALSIM_FindEncoderForChannel(int32_t channel) { return 0; }
+int32_t HALSIM_FindEncoderForChannel(int32_t channel) {
+ return 0;
+}
void HALSIM_ResetEncoderData(int32_t index) {}
-int32_t HALSIM_GetEncoderDigitalChannelA(int32_t index) { return 0; }
+int32_t HALSIM_GetEncoderDigitalChannelA(int32_t index) {
+ return 0;
+}
-int32_t HALSIM_GetEncoderDigitalChannelB(int32_t index) { return 0; }
+int32_t HALSIM_GetEncoderDigitalChannelB(int32_t index) {
+ return 0;
+}
-HAL_SimDeviceHandle HALSIM_GetEncoderSimDevice(int32_t index) { return 0; }
+HAL_SimDeviceHandle HALSIM_GetEncoderSimDevice(int32_t index) {
+ return 0;
+}
#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, Encoder##CAPINAME, RETURN)
@@ -35,11 +40,15 @@
void HALSIM_SetEncoderDistance(int32_t index, double distance) {}
-double HALSIM_GetEncoderDistance(int32_t index) { return 0; }
+double HALSIM_GetEncoderDistance(int32_t index) {
+ return 0;
+}
void HALSIM_SetEncoderRate(int32_t index, double rate) {}
-double HALSIM_GetEncoderRate(int32_t index) { return 0; }
+double HALSIM_GetEncoderRate(int32_t index) {
+ return 0;
+}
void HALSIM_RegisterEncoderAllCallbacks(int32_t index,
HAL_NotifyCallback callback,
diff --git a/hal/src/main/native/athena/mockdata/I2CData.cpp b/hal/src/main/native/athena/mockdata/I2CData.cpp
index eb6a6c9..2f91061 100644
--- a/hal/src/main/native/athena/mockdata/I2CData.cpp
+++ b/hal/src/main/native/athena/mockdata/I2CData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/I2CData.h"
diff --git a/hal/src/main/native/athena/mockdata/MockHooks.cpp b/hal/src/main/native/athena/mockdata/MockHooks.cpp
index 2e7bcfe..0ea05d0 100644
--- a/hal/src/main/native/athena/mockdata/MockHooks.cpp
+++ b/hal/src/main/native/athena/mockdata/MockHooks.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/MockHooks.h"
@@ -15,7 +12,9 @@
void HALSIM_SetProgramStarted(void) {}
-HAL_Bool HALSIM_GetProgramStarted(void) { return false; }
+HAL_Bool HALSIM_GetProgramStarted(void) {
+ return false;
+}
void HALSIM_RestartTiming(void) {}
@@ -23,7 +22,9 @@
void HALSIM_ResumeTiming(void) {}
-HAL_Bool HALSIM_IsTimingPaused(void) { return false; }
+HAL_Bool HALSIM_IsTimingPaused(void) {
+ return false;
+}
void HALSIM_StepTiming(uint64_t delta) {}
@@ -33,4 +34,18 @@
void HALSIM_SetSendConsoleLine(HALSIM_SendConsoleLineHandler handler) {}
+int32_t HALSIM_RegisterSimPeriodicBeforeCallback(
+ HALSIM_SimPeriodicCallback callback, void* param) {
+ return 0;
+}
+
+void HALSIM_CancelSimPeriodicBeforeCallback(int32_t uid) {}
+
+int32_t HALSIM_RegisterSimPeriodicAfterCallback(
+ HALSIM_SimPeriodicCallback callback, void* param) {
+ return 0;
+}
+
+void HALSIM_CancelSimPeriodicAfterCallback(int32_t uid) {}
+
} // extern "C"
diff --git a/hal/src/main/native/athena/mockdata/NotifierData.cpp b/hal/src/main/native/athena/mockdata/NotifierData.cpp
index 34aa6e7..f75733e 100644
--- a/hal/src/main/native/athena/mockdata/NotifierData.cpp
+++ b/hal/src/main/native/athena/mockdata/NotifierData.cpp
@@ -1,17 +1,18 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/NotifierData.h"
extern "C" {
-uint64_t HALSIM_GetNextNotifierTimeout(void) { return 0; }
+uint64_t HALSIM_GetNextNotifierTimeout(void) {
+ return 0;
+}
-int32_t HALSIM_GetNumNotifiers(void) { return 0; }
+int32_t HALSIM_GetNumNotifiers(void) {
+ return 0;
+}
int32_t HALSIM_GetNotifierInfo(struct HALSIM_NotifierInfo* arr, int32_t size) {
return 0;
diff --git a/hal/src/main/native/athena/mockdata/PCMData.cpp b/hal/src/main/native/athena/mockdata/PCMData.cpp
deleted file mode 100644
index 29302cb..0000000
--- a/hal/src/main/native/athena/mockdata/PCMData.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
-
-#include "hal/simulation/PCMData.h"
-
-#include "hal/simulation/SimDataValue.h"
-
-extern "C" {
-void HALSIM_ResetPCMData(int32_t index) {}
-
-#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
- HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, PCM##CAPINAME, RETURN)
-
-HAL_SIMDATAVALUE_STUB_CAPI_CHANNEL(HAL_Bool, HALSIM, PCMSolenoidInitialized,
- false)
-HAL_SIMDATAVALUE_STUB_CAPI_CHANNEL(HAL_Bool, HALSIM, PCMSolenoidOutput, false)
-DEFINE_CAPI(HAL_Bool, CompressorInitialized, false)
-DEFINE_CAPI(HAL_Bool, CompressorOn, false)
-DEFINE_CAPI(HAL_Bool, ClosedLoopEnabled, false)
-DEFINE_CAPI(HAL_Bool, PressureSwitch, false)
-DEFINE_CAPI(double, CompressorCurrent, 0)
-
-void HALSIM_GetPCMAllSolenoids(int32_t index, uint8_t* values) { *values = 0; }
-
-void HALSIM_SetPCMAllSolenoids(int32_t index, uint8_t values) {}
-
-void HALSIM_RegisterPCMAllNonSolenoidCallbacks(int32_t index,
- HAL_NotifyCallback callback,
- void* param,
- HAL_Bool initialNotify) {}
-
-void HALSIM_RegisterPCMAllSolenoidCallbacks(int32_t index, int32_t channel,
- HAL_NotifyCallback callback,
- void* param,
- HAL_Bool initialNotify) {}
-} // extern "C"
diff --git a/hal/src/main/native/athena/mockdata/PDPData.cpp b/hal/src/main/native/athena/mockdata/PDPData.cpp
deleted file mode 100644
index a28bb81..0000000
--- a/hal/src/main/native/athena/mockdata/PDPData.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
-
-#include "hal/simulation/PDPData.h"
-
-#include "../PortsInternal.h"
-#include "hal/simulation/SimDataValue.h"
-
-extern "C" {
-void HALSIM_ResetPDPData(int32_t index) {}
-
-#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
- HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, PDP##CAPINAME, RETURN)
-
-DEFINE_CAPI(HAL_Bool, Initialized, false)
-DEFINE_CAPI(double, Temperature, 0)
-DEFINE_CAPI(double, Voltage, 0)
-HAL_SIMDATAVALUE_STUB_CAPI_CHANNEL(double, HALSIM, PDPCurrent, 0)
-
-void HALSIM_GetPDPAllCurrents(int32_t index, double* currents) {
- for (int i = 0; i < hal::kNumPDPChannels; i++) currents[i] = 0;
-}
-
-void HALSIM_SetPDPAllCurrents(int32_t index, const double* currents) {}
-
-void HALSIM_RegisterPDPAllNonCurrentCallbacks(int32_t index, int32_t channel,
- HAL_NotifyCallback callback,
- void* param,
- HAL_Bool initialNotify) {}
-} // extern "C"
diff --git a/hal/src/main/native/athena/mockdata/PWMData.cpp b/hal/src/main/native/athena/mockdata/PWMData.cpp
index b9c5691..3e12398 100644
--- a/hal/src/main/native/athena/mockdata/PWMData.cpp
+++ b/hal/src/main/native/athena/mockdata/PWMData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/PWMData.h"
diff --git a/hal/src/main/native/athena/mockdata/PowerDistributionData.cpp b/hal/src/main/native/athena/mockdata/PowerDistributionData.cpp
new file mode 100644
index 0000000..a44e222
--- /dev/null
+++ b/hal/src/main/native/athena/mockdata/PowerDistributionData.cpp
@@ -0,0 +1,35 @@
+// 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/simulation/PowerDistributionData.h"
+
+#include "../PortsInternal.h"
+#include "hal/simulation/SimDataValue.h"
+
+extern "C" {
+void HALSIM_ResetPowerDistributionData(int32_t index) {}
+
+#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
+ HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, PowerDistribution##CAPINAME, RETURN)
+
+DEFINE_CAPI(HAL_Bool, Initialized, false)
+DEFINE_CAPI(double, Temperature, 0)
+DEFINE_CAPI(double, Voltage, 0)
+HAL_SIMDATAVALUE_STUB_CAPI_CHANNEL(double, HALSIM, PowerDistributionCurrent, 0)
+
+void HALSIM_GetPowerDistributionAllCurrents(int32_t index, double* currents,
+ int length) {
+ for (int i = 0; i < length; i++) {
+ currents[i] = 0;
+ }
+}
+
+void HALSIM_SetPowerDistributionAllCurrents(int32_t index,
+ const double* currents,
+ int length) {}
+
+void HALSIM_RegisterPowerDistributionAllNonCurrentCallbacks(
+ int32_t index, int32_t channel, HAL_NotifyCallback callback, void* param,
+ HAL_Bool initialNotify) {}
+} // extern "C"
diff --git a/hal/src/main/native/athena/mockdata/REVPHData.cpp b/hal/src/main/native/athena/mockdata/REVPHData.cpp
new file mode 100644
index 0000000..d617694
--- /dev/null
+++ b/hal/src/main/native/athena/mockdata/REVPHData.cpp
@@ -0,0 +1,37 @@
+// 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/simulation/REVPHData.h"
+
+#include "hal/simulation/SimDataValue.h"
+
+extern "C" {
+void HALSIM_ResetREVPHData(int32_t index) {}
+
+#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
+ HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, REVPH##CAPINAME, RETURN)
+
+HAL_SIMDATAVALUE_STUB_CAPI_CHANNEL(HAL_Bool, HALSIM, REVPHSolenoidOutput, false)
+DEFINE_CAPI(HAL_Bool, Initialized, false)
+DEFINE_CAPI(HAL_Bool, CompressorOn, false)
+DEFINE_CAPI(HAL_Bool, ClosedLoopEnabled, false)
+DEFINE_CAPI(HAL_Bool, PressureSwitch, false)
+DEFINE_CAPI(double, CompressorCurrent, 0)
+
+void HALSIM_GetREVPHAllSolenoids(int32_t index, uint8_t* values) {
+ *values = 0;
+}
+
+void HALSIM_SetREVPHAllSolenoids(int32_t index, uint8_t values) {}
+
+void HALSIM_RegisterREVPHAllNonSolenoidCallbacks(int32_t index,
+ HAL_NotifyCallback callback,
+ void* param,
+ HAL_Bool initialNotify) {}
+
+void HALSIM_RegisterREVPHAllSolenoidCallbacks(int32_t index, int32_t channel,
+ HAL_NotifyCallback callback,
+ void* param,
+ HAL_Bool initialNotify) {}
+} // extern "C"
diff --git a/hal/src/main/native/athena/mockdata/RelayData.cpp b/hal/src/main/native/athena/mockdata/RelayData.cpp
index 734bf89..7d8d439 100644
--- a/hal/src/main/native/athena/mockdata/RelayData.cpp
+++ b/hal/src/main/native/athena/mockdata/RelayData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/RelayData.h"
diff --git a/hal/src/main/native/athena/mockdata/RoboRioData.cpp b/hal/src/main/native/athena/mockdata/RoboRioData.cpp
index f9e9ca7..9f6683a 100644
--- a/hal/src/main/native/athena/mockdata/RoboRioData.cpp
+++ b/hal/src/main/native/athena/mockdata/RoboRioData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/RoboRioData.h"
@@ -30,6 +27,7 @@
DEFINE_CAPI(int32_t, UserFaults6V, 0)
DEFINE_CAPI(int32_t, UserFaults5V, 0)
DEFINE_CAPI(int32_t, UserFaults3V3, 0)
+DEFINE_CAPI(double, BrownoutVoltage, 6.75)
void HALSIM_RegisterRoboRioAllCallbacks(HAL_NotifyCallback callback,
void* param, HAL_Bool initialNotify) {}
diff --git a/hal/src/main/native/athena/mockdata/SPIAccelerometerData.cpp b/hal/src/main/native/athena/mockdata/SPIAccelerometerData.cpp
index c3e8ede..c938abf 100644
--- a/hal/src/main/native/athena/mockdata/SPIAccelerometerData.cpp
+++ b/hal/src/main/native/athena/mockdata/SPIAccelerometerData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/SPIAccelerometerData.h"
diff --git a/hal/src/main/native/athena/mockdata/SPIData.cpp b/hal/src/main/native/athena/mockdata/SPIData.cpp
index 13cf67c..433ca10 100644
--- a/hal/src/main/native/athena/mockdata/SPIData.cpp
+++ b/hal/src/main/native/athena/mockdata/SPIData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/SPIData.h"
diff --git a/hal/src/main/native/athena/mockdata/SimDeviceData.cpp b/hal/src/main/native/athena/mockdata/SimDeviceData.cpp
index a31160c..08bd8ce 100644
--- a/hal/src/main/native/athena/mockdata/SimDeviceData.cpp
+++ b/hal/src/main/native/athena/mockdata/SimDeviceData.cpp
@@ -1,9 +1,6 @@
-/*----------------------------------------------------------------------------*/
-/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */
-/* Open Source Software - may be modified and shared by FRC teams. The code */
-/* must be accompanied by the FIRST BSD license file in the root directory of */
-/* the project. */
-/*----------------------------------------------------------------------------*/
+// 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/simulation/SimDeviceData.h"
@@ -13,7 +10,9 @@
void HALSIM_SetSimDeviceEnabled(const char* prefix, HAL_Bool enabled) {}
-HAL_Bool HALSIM_IsSimDeviceEnabled(const char* name) { return false; }
+HAL_Bool HALSIM_IsSimDeviceEnabled(const char* name) {
+ return false;
+}
int32_t HALSIM_RegisterSimDeviceCreatedCallback(
const char* prefix, void* param, HALSIM_SimDeviceCallback callback,
@@ -23,16 +22,21 @@
void HALSIM_CancelSimDeviceCreatedCallback(int32_t uid) {}
-int32_t HALSIM_RegisterSimDeviceFreedCallback(
- const char* prefix, void* param, HALSIM_SimDeviceCallback callback) {
+int32_t HALSIM_RegisterSimDeviceFreedCallback(const char* prefix, void* param,
+ HALSIM_SimDeviceCallback callback,
+ HAL_Bool initialNotify) {
return 0;
}
void HALSIM_CancelSimDeviceFreedCallback(int32_t uid) {}
-HAL_SimDeviceHandle HALSIM_GetSimDeviceHandle(const char* name) { return 0; }
+HAL_SimDeviceHandle HALSIM_GetSimDeviceHandle(const char* name) {
+ return 0;
+}
-const char* HALSIM_GetSimDeviceName(HAL_SimDeviceHandle handle) { return ""; }
+const char* HALSIM_GetSimDeviceName(HAL_SimDeviceHandle handle) {
+ return "";
+}
HAL_SimDeviceHandle HALSIM_GetSimValueDeviceHandle(HAL_SimValueHandle handle) {
return 0;
@@ -59,6 +63,15 @@
void HALSIM_CancelSimValueChangedCallback(int32_t uid) {}
+int32_t HALSIM_RegisterSimValueResetCallback(HAL_SimValueHandle handle,
+ void* param,
+ HALSIM_SimValueCallback callback,
+ HAL_Bool initialNotify) {
+ return 0;
+}
+
+void HALSIM_CancelSimValueResetCallback(int32_t uid) {}
+
HAL_SimValueHandle HALSIM_GetSimValueHandle(HAL_SimDeviceHandle device,
const char* name) {
return 0;
@@ -73,6 +86,12 @@
return nullptr;
}
+const double* HALSIM_GetSimValueEnumDoubleValues(HAL_SimValueHandle handle,
+ int32_t* numOptions) {
+ *numOptions = 0;
+ return nullptr;
+}
+
void HALSIM_ResetSimDeviceData(void) {}
} // extern "C"
diff --git a/hal/src/main/native/athena/rev/PDHFrames.cpp b/hal/src/main/native/athena/rev/PDHFrames.cpp
new file mode 100644
index 0000000..b50a148
--- /dev/null
+++ b/hal/src/main/native/athena/rev/PDHFrames.cpp
@@ -0,0 +1,1790 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Erik Moqvist
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * This file was generated by cantools version
+ */
+
+#include <string.h>
+
+#include "PDHFrames.h"
+
+static inline uint8_t pack_left_shift_u8(
+ uint8_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint8_t)((uint8_t)(value << shift) & mask);
+}
+
+static inline uint8_t pack_left_shift_u16(
+ uint16_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint8_t)((uint8_t)(value << shift) & mask);
+}
+
+static inline uint8_t pack_left_shift_u32(
+ uint32_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint8_t)((uint8_t)(value << shift) & mask);
+}
+
+static inline uint8_t pack_right_shift_u16(
+ uint16_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint8_t)((uint8_t)(value >> shift) & mask);
+}
+
+static inline uint8_t pack_right_shift_u32(
+ uint32_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint8_t)((uint8_t)(value >> shift) & mask);
+}
+
+static inline uint16_t unpack_left_shift_u16(
+ uint8_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint16_t)((uint16_t)(value & mask) << shift);
+}
+
+static inline uint32_t unpack_left_shift_u32(
+ uint8_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint32_t)((uint32_t)(value & mask) << shift);
+}
+
+static inline uint8_t unpack_right_shift_u8(
+ uint8_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint8_t)((uint8_t)(value & mask) >> shift);
+}
+
+static inline uint16_t unpack_right_shift_u16(
+ uint8_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint16_t)((uint16_t)(value & mask) >> shift);
+}
+
+static inline uint32_t unpack_right_shift_u32(
+ uint8_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint32_t)((uint32_t)(value & mask) >> shift);
+}
+
+int PDH_switch_channel_set_pack(
+ uint8_t *dst_p,
+ const struct PDH_switch_channel_set_t *src_p,
+ size_t size)
+{
+ if (size < 1u) {
+ return (-EINVAL);
+ }
+
+ memset(&dst_p[0], 0, 1);
+
+ dst_p[0] |= pack_left_shift_u8(src_p->output_set_value, 0u, 0x01u);
+ dst_p[0] |= pack_left_shift_u8(src_p->use_system_enable, 1u, 0x02u);
+
+ return (1);
+}
+
+int PDH_switch_channel_set_unpack(
+ struct PDH_switch_channel_set_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ if (size < 1u) {
+ return (-EINVAL);
+ }
+
+ dst_p->output_set_value = unpack_right_shift_u8(src_p[0], 0u, 0x01u);
+ dst_p->use_system_enable = unpack_right_shift_u8(src_p[0], 1u, 0x02u);
+
+ return (0);
+}
+
+uint8_t PDH_switch_channel_set_output_set_value_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_switch_channel_set_output_set_value_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_switch_channel_set_output_set_value_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_switch_channel_set_use_system_enable_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_switch_channel_set_use_system_enable_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_switch_channel_set_use_system_enable_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+int PDH_status0_pack(
+ uint8_t *dst_p,
+ const struct PDH_status0_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ memset(&dst_p[0], 0, 8);
+
+ dst_p[0] |= pack_left_shift_u16(src_p->channel_0_current, 0u, 0xffu);
+ dst_p[1] |= pack_right_shift_u16(src_p->channel_0_current, 8u, 0x03u);
+ dst_p[1] |= pack_left_shift_u16(src_p->channel_1_current, 2u, 0xfcu);
+ dst_p[2] |= pack_right_shift_u16(src_p->channel_1_current, 6u, 0x0fu);
+ dst_p[2] |= pack_left_shift_u16(src_p->channel_2_current, 4u, 0xf0u);
+ dst_p[3] |= pack_right_shift_u16(src_p->channel_2_current, 4u, 0x3fu);
+ dst_p[3] |= pack_left_shift_u8(src_p->channel_0_brownout, 6u, 0x40u);
+ dst_p[3] |= pack_left_shift_u8(src_p->channel_1_brownout, 7u, 0x80u);
+ dst_p[4] |= pack_left_shift_u16(src_p->channel_3_current, 0u, 0xffu);
+ dst_p[5] |= pack_right_shift_u16(src_p->channel_3_current, 8u, 0x03u);
+ dst_p[5] |= pack_left_shift_u16(src_p->channel_4_current, 2u, 0xfcu);
+ dst_p[6] |= pack_right_shift_u16(src_p->channel_4_current, 6u, 0x0fu);
+ dst_p[6] |= pack_left_shift_u16(src_p->channel_5_current, 4u, 0xf0u);
+ dst_p[7] |= pack_right_shift_u16(src_p->channel_5_current, 4u, 0x3fu);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_2_brownout, 6u, 0x40u);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_3_brownout, 7u, 0x80u);
+
+ return (8);
+}
+
+int PDH_status0_unpack(
+ struct PDH_status0_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ dst_p->channel_0_current = unpack_right_shift_u16(src_p[0], 0u, 0xffu);
+ dst_p->channel_0_current |= unpack_left_shift_u16(src_p[1], 8u, 0x03u);
+ dst_p->channel_1_current = unpack_right_shift_u16(src_p[1], 2u, 0xfcu);
+ dst_p->channel_1_current |= unpack_left_shift_u16(src_p[2], 6u, 0x0fu);
+ dst_p->channel_2_current = unpack_right_shift_u16(src_p[2], 4u, 0xf0u);
+ dst_p->channel_2_current |= unpack_left_shift_u16(src_p[3], 4u, 0x3fu);
+ dst_p->channel_0_brownout = unpack_right_shift_u8(src_p[3], 6u, 0x40u);
+ dst_p->channel_1_brownout = unpack_right_shift_u8(src_p[3], 7u, 0x80u);
+ dst_p->channel_3_current = unpack_right_shift_u16(src_p[4], 0u, 0xffu);
+ dst_p->channel_3_current |= unpack_left_shift_u16(src_p[5], 8u, 0x03u);
+ dst_p->channel_4_current = unpack_right_shift_u16(src_p[5], 2u, 0xfcu);
+ dst_p->channel_4_current |= unpack_left_shift_u16(src_p[6], 6u, 0x0fu);
+ dst_p->channel_5_current = unpack_right_shift_u16(src_p[6], 4u, 0xf0u);
+ dst_p->channel_5_current |= unpack_left_shift_u16(src_p[7], 4u, 0x3fu);
+ dst_p->channel_2_brownout = unpack_right_shift_u8(src_p[7], 6u, 0x40u);
+ dst_p->channel_3_brownout = unpack_right_shift_u8(src_p[7], 7u, 0x80u);
+
+ return (0);
+}
+
+uint16_t PDH_status0_channel_0_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status0_channel_0_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status0_channel_0_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status0_channel_1_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status0_channel_1_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status0_channel_1_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status0_channel_2_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status0_channel_2_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status0_channel_2_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint8_t PDH_status0_channel_0_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status0_channel_0_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status0_channel_0_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status0_channel_1_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status0_channel_1_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status0_channel_1_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint16_t PDH_status0_channel_3_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status0_channel_3_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status0_channel_3_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status0_channel_4_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status0_channel_4_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status0_channel_4_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status0_channel_5_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status0_channel_5_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status0_channel_5_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint8_t PDH_status0_channel_2_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status0_channel_2_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status0_channel_2_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status0_channel_3_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status0_channel_3_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status0_channel_3_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+int PDH_status1_pack(
+ uint8_t *dst_p,
+ const struct PDH_status1_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ memset(&dst_p[0], 0, 8);
+
+ dst_p[0] |= pack_left_shift_u16(src_p->channel_6_current, 0u, 0xffu);
+ dst_p[1] |= pack_right_shift_u16(src_p->channel_6_current, 8u, 0x03u);
+ dst_p[1] |= pack_left_shift_u16(src_p->channel_7_current, 2u, 0xfcu);
+ dst_p[2] |= pack_right_shift_u16(src_p->channel_7_current, 6u, 0x0fu);
+ dst_p[2] |= pack_left_shift_u16(src_p->channel_8_current, 4u, 0xf0u);
+ dst_p[3] |= pack_right_shift_u16(src_p->channel_8_current, 4u, 0x3fu);
+ dst_p[3] |= pack_left_shift_u8(src_p->channel_4_brownout, 6u, 0x40u);
+ dst_p[3] |= pack_left_shift_u8(src_p->channel_5_brownout, 7u, 0x80u);
+ dst_p[4] |= pack_left_shift_u16(src_p->channel_9_current, 0u, 0xffu);
+ dst_p[5] |= pack_right_shift_u16(src_p->channel_9_current, 8u, 0x03u);
+ dst_p[5] |= pack_left_shift_u16(src_p->channel_10_current, 2u, 0xfcu);
+ dst_p[6] |= pack_right_shift_u16(src_p->channel_10_current, 6u, 0x0fu);
+ dst_p[6] |= pack_left_shift_u16(src_p->channel_11_current, 4u, 0xf0u);
+ dst_p[7] |= pack_right_shift_u16(src_p->channel_11_current, 4u, 0x3fu);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_6_brownout, 6u, 0x40u);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_7_brownout, 7u, 0x80u);
+
+ return (8);
+}
+
+int PDH_status1_unpack(
+ struct PDH_status1_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ dst_p->channel_6_current = unpack_right_shift_u16(src_p[0], 0u, 0xffu);
+ dst_p->channel_6_current |= unpack_left_shift_u16(src_p[1], 8u, 0x03u);
+ dst_p->channel_7_current = unpack_right_shift_u16(src_p[1], 2u, 0xfcu);
+ dst_p->channel_7_current |= unpack_left_shift_u16(src_p[2], 6u, 0x0fu);
+ dst_p->channel_8_current = unpack_right_shift_u16(src_p[2], 4u, 0xf0u);
+ dst_p->channel_8_current |= unpack_left_shift_u16(src_p[3], 4u, 0x3fu);
+ dst_p->channel_4_brownout = unpack_right_shift_u8(src_p[3], 6u, 0x40u);
+ dst_p->channel_5_brownout = unpack_right_shift_u8(src_p[3], 7u, 0x80u);
+ dst_p->channel_9_current = unpack_right_shift_u16(src_p[4], 0u, 0xffu);
+ dst_p->channel_9_current |= unpack_left_shift_u16(src_p[5], 8u, 0x03u);
+ dst_p->channel_10_current = unpack_right_shift_u16(src_p[5], 2u, 0xfcu);
+ dst_p->channel_10_current |= unpack_left_shift_u16(src_p[6], 6u, 0x0fu);
+ dst_p->channel_11_current = unpack_right_shift_u16(src_p[6], 4u, 0xf0u);
+ dst_p->channel_11_current |= unpack_left_shift_u16(src_p[7], 4u, 0x3fu);
+ dst_p->channel_6_brownout = unpack_right_shift_u8(src_p[7], 6u, 0x40u);
+ dst_p->channel_7_brownout = unpack_right_shift_u8(src_p[7], 7u, 0x80u);
+
+ return (0);
+}
+
+uint16_t PDH_status1_channel_6_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status1_channel_6_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status1_channel_6_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status1_channel_7_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status1_channel_7_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status1_channel_7_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status1_channel_8_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status1_channel_8_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status1_channel_8_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint8_t PDH_status1_channel_4_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status1_channel_4_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status1_channel_4_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status1_channel_5_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status1_channel_5_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status1_channel_5_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint16_t PDH_status1_channel_9_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status1_channel_9_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status1_channel_9_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status1_channel_10_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status1_channel_10_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status1_channel_10_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status1_channel_11_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status1_channel_11_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status1_channel_11_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint8_t PDH_status1_channel_6_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status1_channel_6_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status1_channel_6_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status1_channel_7_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status1_channel_7_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status1_channel_7_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+int PDH_status2_pack(
+ uint8_t *dst_p,
+ const struct PDH_status2_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ memset(&dst_p[0], 0, 8);
+
+ dst_p[0] |= pack_left_shift_u16(src_p->channel_12_current, 0u, 0xffu);
+ dst_p[1] |= pack_right_shift_u16(src_p->channel_12_current, 8u, 0x03u);
+ dst_p[1] |= pack_left_shift_u16(src_p->channel_13_current, 2u, 0xfcu);
+ dst_p[2] |= pack_right_shift_u16(src_p->channel_13_current, 6u, 0x0fu);
+ dst_p[2] |= pack_left_shift_u16(src_p->channel_14_current, 4u, 0xf0u);
+ dst_p[3] |= pack_right_shift_u16(src_p->channel_14_current, 4u, 0x3fu);
+ dst_p[3] |= pack_left_shift_u8(src_p->channel_8_brownout, 6u, 0x40u);
+ dst_p[3] |= pack_left_shift_u8(src_p->channel_9_brownout, 7u, 0x80u);
+ dst_p[4] |= pack_left_shift_u16(src_p->channel_15_current, 0u, 0xffu);
+ dst_p[5] |= pack_right_shift_u16(src_p->channel_15_current, 8u, 0x03u);
+ dst_p[5] |= pack_left_shift_u16(src_p->channel_16_current, 2u, 0xfcu);
+ dst_p[6] |= pack_right_shift_u16(src_p->channel_16_current, 6u, 0x0fu);
+ dst_p[6] |= pack_left_shift_u16(src_p->channel_17_current, 4u, 0xf0u);
+ dst_p[7] |= pack_right_shift_u16(src_p->channel_17_current, 4u, 0x3fu);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_10_brownout, 6u, 0x40u);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_11_brownout, 7u, 0x80u);
+
+ return (8);
+}
+
+int PDH_status2_unpack(
+ struct PDH_status2_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ dst_p->channel_12_current = unpack_right_shift_u16(src_p[0], 0u, 0xffu);
+ dst_p->channel_12_current |= unpack_left_shift_u16(src_p[1], 8u, 0x03u);
+ dst_p->channel_13_current = unpack_right_shift_u16(src_p[1], 2u, 0xfcu);
+ dst_p->channel_13_current |= unpack_left_shift_u16(src_p[2], 6u, 0x0fu);
+ dst_p->channel_14_current = unpack_right_shift_u16(src_p[2], 4u, 0xf0u);
+ dst_p->channel_14_current |= unpack_left_shift_u16(src_p[3], 4u, 0x3fu);
+ dst_p->channel_8_brownout = unpack_right_shift_u8(src_p[3], 6u, 0x40u);
+ dst_p->channel_9_brownout = unpack_right_shift_u8(src_p[3], 7u, 0x80u);
+ dst_p->channel_15_current = unpack_right_shift_u16(src_p[4], 0u, 0xffu);
+ dst_p->channel_15_current |= unpack_left_shift_u16(src_p[5], 8u, 0x03u);
+ dst_p->channel_16_current = unpack_right_shift_u16(src_p[5], 2u, 0xfcu);
+ dst_p->channel_16_current |= unpack_left_shift_u16(src_p[6], 6u, 0x0fu);
+ dst_p->channel_17_current = unpack_right_shift_u16(src_p[6], 4u, 0xf0u);
+ dst_p->channel_17_current |= unpack_left_shift_u16(src_p[7], 4u, 0x3fu);
+ dst_p->channel_10_brownout = unpack_right_shift_u8(src_p[7], 6u, 0x40u);
+ dst_p->channel_11_brownout = unpack_right_shift_u8(src_p[7], 7u, 0x80u);
+
+ return (0);
+}
+
+uint16_t PDH_status2_channel_12_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status2_channel_12_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status2_channel_12_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status2_channel_13_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status2_channel_13_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status2_channel_13_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status2_channel_14_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status2_channel_14_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status2_channel_14_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint8_t PDH_status2_channel_8_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status2_channel_8_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status2_channel_8_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status2_channel_9_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status2_channel_9_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status2_channel_9_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint16_t PDH_status2_channel_15_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status2_channel_15_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status2_channel_15_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status2_channel_16_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status2_channel_16_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status2_channel_16_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status2_channel_17_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status2_channel_17_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status2_channel_17_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint8_t PDH_status2_channel_10_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status2_channel_10_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status2_channel_10_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status2_channel_11_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status2_channel_11_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status2_channel_11_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+int PDH_status3_pack(
+ uint8_t *dst_p,
+ const struct PDH_status3_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ memset(&dst_p[0], 0, 8);
+
+ dst_p[0] |= pack_left_shift_u16(src_p->channel_18_current, 0u, 0xffu);
+ dst_p[1] |= pack_right_shift_u16(src_p->channel_18_current, 8u, 0x03u);
+ dst_p[1] |= pack_left_shift_u16(src_p->channel_19_current, 2u, 0xfcu);
+ dst_p[2] |= pack_right_shift_u16(src_p->channel_19_current, 6u, 0x0fu);
+ dst_p[2] |= pack_left_shift_u8(src_p->channel_12_brownout, 4u, 0x10u);
+ dst_p[2] |= pack_left_shift_u8(src_p->channel_13_brownout, 5u, 0x20u);
+ dst_p[2] |= pack_left_shift_u8(src_p->channel_14_brownout, 6u, 0x40u);
+ dst_p[2] |= pack_left_shift_u8(src_p->channel_15_brownout, 7u, 0x80u);
+ dst_p[3] |= pack_left_shift_u8(src_p->channel_20_current, 0u, 0xffu);
+ dst_p[4] |= pack_left_shift_u8(src_p->channel_21_current, 0u, 0xffu);
+ dst_p[5] |= pack_left_shift_u8(src_p->channel_22_current, 0u, 0xffu);
+ dst_p[6] |= pack_left_shift_u8(src_p->channel_23_current, 0u, 0xffu);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_16_brownout, 0u, 0x01u);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_17_brownout, 1u, 0x02u);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_18_brownout, 2u, 0x04u);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_19_brownout, 3u, 0x08u);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_20_brownout, 4u, 0x10u);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_21_brownout, 5u, 0x20u);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_22_brownout, 6u, 0x40u);
+ dst_p[7] |= pack_left_shift_u8(src_p->channel_23_brownout, 7u, 0x80u);
+
+ return (8);
+}
+
+int PDH_status3_unpack(
+ struct PDH_status3_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ dst_p->channel_18_current = unpack_right_shift_u16(src_p[0], 0u, 0xffu);
+ dst_p->channel_18_current |= unpack_left_shift_u16(src_p[1], 8u, 0x03u);
+ dst_p->channel_19_current = unpack_right_shift_u16(src_p[1], 2u, 0xfcu);
+ dst_p->channel_19_current |= unpack_left_shift_u16(src_p[2], 6u, 0x0fu);
+ dst_p->channel_12_brownout = unpack_right_shift_u8(src_p[2], 4u, 0x10u);
+ dst_p->channel_13_brownout = unpack_right_shift_u8(src_p[2], 5u, 0x20u);
+ dst_p->channel_14_brownout = unpack_right_shift_u8(src_p[2], 6u, 0x40u);
+ dst_p->channel_15_brownout = unpack_right_shift_u8(src_p[2], 7u, 0x80u);
+ dst_p->channel_20_current = unpack_right_shift_u8(src_p[3], 0u, 0xffu);
+ dst_p->channel_21_current = unpack_right_shift_u8(src_p[4], 0u, 0xffu);
+ dst_p->channel_22_current = unpack_right_shift_u8(src_p[5], 0u, 0xffu);
+ dst_p->channel_23_current = unpack_right_shift_u8(src_p[6], 0u, 0xffu);
+ dst_p->channel_16_brownout = unpack_right_shift_u8(src_p[7], 0u, 0x01u);
+ dst_p->channel_17_brownout = unpack_right_shift_u8(src_p[7], 1u, 0x02u);
+ dst_p->channel_18_brownout = unpack_right_shift_u8(src_p[7], 2u, 0x04u);
+ dst_p->channel_19_brownout = unpack_right_shift_u8(src_p[7], 3u, 0x08u);
+ dst_p->channel_20_brownout = unpack_right_shift_u8(src_p[7], 4u, 0x10u);
+ dst_p->channel_21_brownout = unpack_right_shift_u8(src_p[7], 5u, 0x20u);
+ dst_p->channel_22_brownout = unpack_right_shift_u8(src_p[7], 6u, 0x40u);
+ dst_p->channel_23_brownout = unpack_right_shift_u8(src_p[7], 7u, 0x80u);
+
+ return (0);
+}
+
+uint16_t PDH_status3_channel_18_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status3_channel_18_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status3_channel_18_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint16_t PDH_status3_channel_19_current_encode(double value)
+{
+ return (uint16_t)(value / 0.125);
+}
+
+double PDH_status3_channel_19_current_decode(uint16_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PDH_status3_channel_19_current_is_in_range(uint16_t value)
+{
+ return (value <= 1023u);
+}
+
+uint8_t PDH_status3_channel_12_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status3_channel_12_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status3_channel_12_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status3_channel_13_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status3_channel_13_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status3_channel_13_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status3_channel_14_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status3_channel_14_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status3_channel_14_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status3_channel_15_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status3_channel_15_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status3_channel_15_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status3_channel_20_current_encode(double value)
+{
+ return (uint8_t)(value / 0.0625);
+}
+
+double PDH_status3_channel_20_current_decode(uint8_t value)
+{
+ return ((double)value * 0.0625);
+}
+
+bool PDH_status3_channel_20_current_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+uint8_t PDH_status3_channel_21_current_encode(double value)
+{
+ return (uint8_t)(value / 0.0625);
+}
+
+double PDH_status3_channel_21_current_decode(uint8_t value)
+{
+ return ((double)value * 0.0625);
+}
+
+bool PDH_status3_channel_21_current_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+uint8_t PDH_status3_channel_22_current_encode(double value)
+{
+ return (uint8_t)(value / 0.0625);
+}
+
+double PDH_status3_channel_22_current_decode(uint8_t value)
+{
+ return ((double)value * 0.0625);
+}
+
+bool PDH_status3_channel_22_current_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+uint8_t PDH_status3_channel_23_current_encode(double value)
+{
+ return (uint8_t)(value / 0.0625);
+}
+
+double PDH_status3_channel_23_current_decode(uint8_t value)
+{
+ return ((double)value * 0.0625);
+}
+
+bool PDH_status3_channel_23_current_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+uint8_t PDH_status3_channel_16_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status3_channel_16_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status3_channel_16_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status3_channel_17_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status3_channel_17_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status3_channel_17_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status3_channel_18_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status3_channel_18_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status3_channel_18_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status3_channel_19_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status3_channel_19_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status3_channel_19_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status3_channel_20_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status3_channel_20_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status3_channel_20_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status3_channel_21_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status3_channel_21_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status3_channel_21_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status3_channel_22_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status3_channel_22_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status3_channel_22_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status3_channel_23_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status3_channel_23_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status3_channel_23_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+int PDH_status4_pack(
+ uint8_t *dst_p,
+ const struct PDH_status4_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ memset(&dst_p[0], 0, 8);
+
+ dst_p[0] |= pack_left_shift_u16(src_p->v_bus, 0u, 0xffu);
+ dst_p[1] |= pack_right_shift_u16(src_p->v_bus, 8u, 0x0fu);
+ dst_p[1] |= pack_left_shift_u8(src_p->system_enable, 4u, 0x10u);
+ dst_p[1] |= pack_left_shift_u8(src_p->rsvd0, 5u, 0xe0u);
+ dst_p[2] |= pack_left_shift_u8(src_p->brownout, 0u, 0x01u);
+ dst_p[2] |= pack_left_shift_u8(src_p->rsvd1, 1u, 0x02u);
+ dst_p[2] |= pack_left_shift_u8(src_p->can_warning, 2u, 0x04u);
+ dst_p[2] |= pack_left_shift_u8(src_p->hardware_fault, 3u, 0x08u);
+ dst_p[2] |= pack_left_shift_u8(src_p->sw_state, 4u, 0x10u);
+ dst_p[2] |= pack_left_shift_u8(src_p->sticky_brownout, 5u, 0x20u);
+ dst_p[2] |= pack_left_shift_u8(src_p->rsvd2, 6u, 0x40u);
+ dst_p[2] |= pack_left_shift_u8(src_p->sticky_can_warning, 7u, 0x80u);
+ dst_p[3] |= pack_left_shift_u8(src_p->sticky_can_bus_off, 0u, 0x01u);
+ dst_p[3] |= pack_left_shift_u8(src_p->sticky_hardware_fault, 1u, 0x02u);
+ dst_p[3] |= pack_left_shift_u8(src_p->sticky_firmware_fault, 2u, 0x04u);
+ dst_p[3] |= pack_left_shift_u8(src_p->sticky_ch20_brownout, 3u, 0x08u);
+ dst_p[3] |= pack_left_shift_u8(src_p->sticky_ch21_brownout, 4u, 0x10u);
+ dst_p[3] |= pack_left_shift_u8(src_p->sticky_ch22_brownout, 5u, 0x20u);
+ dst_p[3] |= pack_left_shift_u8(src_p->sticky_ch23_brownout, 6u, 0x40u);
+ dst_p[3] |= pack_left_shift_u8(src_p->sticky_has_reset, 7u, 0x80u);
+ dst_p[4] |= pack_left_shift_u8(src_p->total_current, 0u, 0xffu);
+
+ return (8);
+}
+
+int PDH_status4_unpack(
+ struct PDH_status4_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ dst_p->v_bus = unpack_right_shift_u16(src_p[0], 0u, 0xffu);
+ dst_p->v_bus |= unpack_left_shift_u16(src_p[1], 8u, 0x0fu);
+ dst_p->system_enable = unpack_right_shift_u8(src_p[1], 4u, 0x10u);
+ dst_p->rsvd0 = unpack_right_shift_u8(src_p[1], 5u, 0xe0u);
+ dst_p->brownout = unpack_right_shift_u8(src_p[2], 0u, 0x01u);
+ dst_p->rsvd1 = unpack_right_shift_u8(src_p[2], 1u, 0x02u);
+ dst_p->can_warning = unpack_right_shift_u8(src_p[2], 2u, 0x04u);
+ dst_p->hardware_fault = unpack_right_shift_u8(src_p[2], 3u, 0x08u);
+ dst_p->sw_state = unpack_right_shift_u8(src_p[2], 4u, 0x10u);
+ dst_p->sticky_brownout = unpack_right_shift_u8(src_p[2], 5u, 0x20u);
+ dst_p->rsvd2 = unpack_right_shift_u8(src_p[2], 6u, 0x40u);
+ dst_p->sticky_can_warning = unpack_right_shift_u8(src_p[2], 7u, 0x80u);
+ dst_p->sticky_can_bus_off = unpack_right_shift_u8(src_p[3], 0u, 0x01u);
+ dst_p->sticky_hardware_fault = unpack_right_shift_u8(src_p[3], 1u, 0x02u);
+ dst_p->sticky_firmware_fault = unpack_right_shift_u8(src_p[3], 2u, 0x04u);
+ dst_p->sticky_ch20_brownout = unpack_right_shift_u8(src_p[3], 3u, 0x08u);
+ dst_p->sticky_ch21_brownout = unpack_right_shift_u8(src_p[3], 4u, 0x10u);
+ dst_p->sticky_ch22_brownout = unpack_right_shift_u8(src_p[3], 5u, 0x20u);
+ dst_p->sticky_ch23_brownout = unpack_right_shift_u8(src_p[3], 6u, 0x40u);
+ dst_p->sticky_has_reset = unpack_right_shift_u8(src_p[3], 7u, 0x80u);
+ dst_p->total_current = unpack_right_shift_u8(src_p[4], 0u, 0xffu);
+
+ return (0);
+}
+
+uint16_t PDH_status4_v_bus_encode(double value)
+{
+ return (uint16_t)(value / 0.0078125);
+}
+
+double PDH_status4_v_bus_decode(uint16_t value)
+{
+ return ((double)value * 0.0078125);
+}
+
+bool PDH_status4_v_bus_is_in_range(uint16_t value)
+{
+ return (value <= 4095u);
+}
+
+uint8_t PDH_status4_system_enable_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_system_enable_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_system_enable_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_rsvd0_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_rsvd0_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_rsvd0_is_in_range(uint8_t value)
+{
+ return (value <= 7u);
+}
+
+uint8_t PDH_status4_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_rsvd1_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_rsvd1_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_rsvd1_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_can_warning_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_can_warning_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_can_warning_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_hardware_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_hardware_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_hardware_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_sw_state_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_sw_state_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_sw_state_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_sticky_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_sticky_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_sticky_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_rsvd2_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_rsvd2_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_rsvd2_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_sticky_can_warning_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_sticky_can_warning_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_sticky_can_warning_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_sticky_can_bus_off_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_sticky_can_bus_off_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_sticky_can_bus_off_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_sticky_hardware_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_sticky_hardware_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_sticky_hardware_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_sticky_firmware_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_sticky_firmware_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_sticky_firmware_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_sticky_ch20_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_sticky_ch20_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_sticky_ch20_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_sticky_ch21_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_sticky_ch21_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_sticky_ch21_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_sticky_ch22_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_sticky_ch22_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_sticky_ch22_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_sticky_ch23_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_sticky_ch23_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_sticky_ch23_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_sticky_has_reset_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_status4_sticky_has_reset_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_status4_sticky_has_reset_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PDH_status4_total_current_encode(double value)
+{
+ return (uint8_t)(value / 2.0);
+}
+
+double PDH_status4_total_current_decode(uint8_t value)
+{
+ return ((double)value * 2.0);
+}
+
+bool PDH_status4_total_current_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+int PDH_clear_faults_pack(
+ uint8_t *dst_p,
+ const struct PDH_clear_faults_t *src_p,
+ size_t size)
+{
+ (void)dst_p;
+ (void)src_p;
+ (void)size;
+
+ return (0);
+}
+
+int PDH_clear_faults_unpack(
+ struct PDH_clear_faults_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ (void)dst_p;
+ (void)src_p;
+ (void)size;
+
+ return (0);
+}
+
+int PDH_identify_pack(
+ uint8_t *dst_p,
+ const struct PDH_identify_t *src_p,
+ size_t size)
+{
+ (void)dst_p;
+ (void)src_p;
+ (void)size;
+
+ return (0);
+}
+
+int PDH_identify_unpack(
+ struct PDH_identify_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ (void)dst_p;
+ (void)src_p;
+ (void)size;
+
+ return (0);
+}
+
+int PDH_version_pack(
+ uint8_t *dst_p,
+ const struct PDH_version_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ memset(&dst_p[0], 0, 8);
+
+ dst_p[0] |= pack_left_shift_u8(src_p->firmware_fix, 0u, 0xffu);
+ dst_p[1] |= pack_left_shift_u8(src_p->firmware_minor, 0u, 0xffu);
+ dst_p[2] |= pack_left_shift_u8(src_p->firmware_year, 0u, 0xffu);
+ dst_p[3] |= pack_left_shift_u8(src_p->hardware_code, 0u, 0xffu);
+ dst_p[4] |= pack_left_shift_u32(src_p->unique_id, 0u, 0xffu);
+ dst_p[5] |= pack_right_shift_u32(src_p->unique_id, 8u, 0xffu);
+ dst_p[6] |= pack_right_shift_u32(src_p->unique_id, 16u, 0xffu);
+ dst_p[7] |= pack_right_shift_u32(src_p->unique_id, 24u, 0xffu);
+
+ return (8);
+}
+
+int PDH_version_unpack(
+ struct PDH_version_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ dst_p->firmware_fix = unpack_right_shift_u8(src_p[0], 0u, 0xffu);
+ dst_p->firmware_minor = unpack_right_shift_u8(src_p[1], 0u, 0xffu);
+ dst_p->firmware_year = unpack_right_shift_u8(src_p[2], 0u, 0xffu);
+ dst_p->hardware_code = unpack_right_shift_u8(src_p[3], 0u, 0xffu);
+ dst_p->unique_id = unpack_right_shift_u32(src_p[4], 0u, 0xffu);
+ dst_p->unique_id |= unpack_left_shift_u32(src_p[5], 8u, 0xffu);
+ dst_p->unique_id |= unpack_left_shift_u32(src_p[6], 16u, 0xffu);
+ dst_p->unique_id |= unpack_left_shift_u32(src_p[7], 24u, 0xffu);
+
+ return (0);
+}
+
+uint8_t PDH_version_firmware_fix_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_version_firmware_fix_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_version_firmware_fix_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+uint8_t PDH_version_firmware_minor_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_version_firmware_minor_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_version_firmware_minor_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+uint8_t PDH_version_firmware_year_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_version_firmware_year_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_version_firmware_year_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+uint8_t PDH_version_hardware_code_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_version_hardware_code_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_version_hardware_code_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+uint32_t PDH_version_unique_id_encode(double value)
+{
+ return (uint32_t)(value);
+}
+
+double PDH_version_unique_id_decode(uint32_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_version_unique_id_is_in_range(uint32_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+int PDH_configure_hr_channel_pack(
+ uint8_t *dst_p,
+ const struct PDH_configure_hr_channel_t *src_p,
+ size_t size)
+{
+ if (size < 3u) {
+ return (-EINVAL);
+ }
+
+ memset(&dst_p[0], 0, 3);
+
+ dst_p[0] |= pack_left_shift_u8(src_p->channel, 0u, 0xffu);
+ dst_p[1] |= pack_left_shift_u16(src_p->period, 0u, 0xffu);
+ dst_p[2] |= pack_right_shift_u16(src_p->period, 8u, 0xffu);
+
+ return (3);
+}
+
+int PDH_configure_hr_channel_unpack(
+ struct PDH_configure_hr_channel_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ if (size < 3u) {
+ return (-EINVAL);
+ }
+
+ dst_p->channel = unpack_right_shift_u8(src_p[0], 0u, 0xffu);
+ dst_p->period = unpack_right_shift_u16(src_p[1], 0u, 0xffu);
+ dst_p->period |= unpack_left_shift_u16(src_p[2], 8u, 0xffu);
+
+ return (0);
+}
+
+uint8_t PDH_configure_hr_channel_channel_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PDH_configure_hr_channel_channel_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_configure_hr_channel_channel_is_in_range(uint8_t value)
+{
+ return (value <= 23u);
+}
+
+uint16_t PDH_configure_hr_channel_period_encode(double value)
+{
+ return (uint16_t)(value);
+}
+
+double PDH_configure_hr_channel_period_decode(uint16_t value)
+{
+ return ((double)value);
+}
+
+bool PDH_configure_hr_channel_period_is_in_range(uint16_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+int PDH_enter_bootloader_pack(
+ uint8_t *dst_p,
+ const struct PDH_enter_bootloader_t *src_p,
+ size_t size)
+{
+ (void)dst_p;
+ (void)src_p;
+ (void)size;
+
+ return (0);
+}
+
+int PDH_enter_bootloader_unpack(
+ struct PDH_enter_bootloader_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ (void)dst_p;
+ (void)src_p;
+ (void)size;
+
+ return (0);
+}
diff --git a/hal/src/main/native/athena/rev/PDHFrames.h b/hal/src/main/native/athena/rev/PDHFrames.h
new file mode 100644
index 0000000..5d2452a
--- /dev/null
+++ b/hal/src/main/native/athena/rev/PDHFrames.h
@@ -0,0 +1,3136 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Erik Moqvist
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * This file was generated by cantools version
+ */
+
+#ifndef PDH_H
+#define PDH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifndef EINVAL
+# define EINVAL 22
+#endif
+
+/* Frame ids. */
+#define PDH_SWITCH_CHANNEL_SET_FRAME_ID (0x8050840u)
+#define PDH_STATUS0_FRAME_ID (0x8051800u)
+#define PDH_STATUS1_FRAME_ID (0x8051840u)
+#define PDH_STATUS2_FRAME_ID (0x8051880u)
+#define PDH_STATUS3_FRAME_ID (0x80518c0u)
+#define PDH_STATUS4_FRAME_ID (0x8051900u)
+#define PDH_CLEAR_FAULTS_FRAME_ID (0x8051b80u)
+#define PDH_IDENTIFY_FRAME_ID (0x8051d80u)
+#define PDH_VERSION_FRAME_ID (0x8052600u)
+#define PDH_CONFIGURE_HR_CHANNEL_FRAME_ID (0x80538c0u)
+#define PDH_ENTER_BOOTLOADER_FRAME_ID (0x8057fc0u)
+
+/* Frame lengths in bytes. */
+#define PDH_SWITCH_CHANNEL_SET_LENGTH (1u)
+#define PDH_STATUS0_LENGTH (8u)
+#define PDH_STATUS1_LENGTH (8u)
+#define PDH_STATUS2_LENGTH (8u)
+#define PDH_STATUS3_LENGTH (8u)
+#define PDH_STATUS4_LENGTH (8u)
+#define PDH_CLEAR_FAULTS_LENGTH (0u)
+#define PDH_IDENTIFY_LENGTH (0u)
+#define PDH_VERSION_LENGTH (8u)
+#define PDH_CONFIGURE_HR_CHANNEL_LENGTH (3u)
+#define PDH_ENTER_BOOTLOADER_LENGTH (0u)
+
+/* Extended or standard frame types. */
+#define PDH_SWITCH_CHANNEL_SET_IS_EXTENDED (1)
+#define PDH_STATUS0_IS_EXTENDED (1)
+#define PDH_STATUS1_IS_EXTENDED (1)
+#define PDH_STATUS2_IS_EXTENDED (1)
+#define PDH_STATUS3_IS_EXTENDED (1)
+#define PDH_STATUS4_IS_EXTENDED (1)
+#define PDH_CLEAR_FAULTS_IS_EXTENDED (1)
+#define PDH_IDENTIFY_IS_EXTENDED (1)
+#define PDH_VERSION_IS_EXTENDED (1)
+#define PDH_CONFIGURE_HR_CHANNEL_IS_EXTENDED (1)
+#define PDH_ENTER_BOOTLOADER_IS_EXTENDED (1)
+
+/* Frame cycle times in milliseconds. */
+
+
+/* Signal choices. */
+
+
+/**
+ * Signals in message SwitchChannelSet.
+ *
+ * Set the switch channel output
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PDH_switch_channel_set_t {
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t output_set_value : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t use_system_enable : 1;
+};
+
+/**
+ * Signals in message Status0.
+ *
+ * Periodic status frame 0
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PDH_status0_t {
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_0_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_1_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_2_current : 10;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_0_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_1_brownout : 1;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_3_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_4_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_5_current : 10;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_2_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_3_brownout : 1;
+};
+
+/**
+ * Signals in message Status1.
+ *
+ * Periodic status frame 1
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PDH_status1_t {
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_6_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_7_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_8_current : 10;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_4_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_5_brownout : 1;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_9_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_10_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_11_current : 10;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_6_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_7_brownout : 1;
+};
+
+/**
+ * Signals in message Status2.
+ *
+ * Periodic status frame 2
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PDH_status2_t {
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_12_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_13_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_14_current : 10;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_8_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_9_brownout : 1;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_15_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_16_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_17_current : 10;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_10_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_11_brownout : 1;
+};
+
+/**
+ * Signals in message Status3.
+ *
+ * Periodic status frame 3
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PDH_status3_t {
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_18_current : 10;
+
+ /**
+ * Range: 0..1023 (0..127.875 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint16_t channel_19_current : 10;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_12_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_13_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_14_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_15_brownout : 1;
+
+ /**
+ * Range: 0..255 (0..15.9375 A)
+ * Scale: 0.0625
+ * Offset: 0
+ */
+ uint8_t channel_20_current : 8;
+
+ /**
+ * Range: 0..255 (0..15.9375 A)
+ * Scale: 0.0625
+ * Offset: 0
+ */
+ uint8_t channel_21_current : 8;
+
+ /**
+ * Range: 0..511 (0..31.9375 A)
+ * Scale: 0.0625
+ * Offset: 0
+ */
+ uint8_t channel_22_current : 8;
+
+ /**
+ * Range: 0..511 (0..31.9375 A)
+ * Scale: 0.0625
+ * Offset: 0
+ */
+ uint8_t channel_23_current : 8;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_16_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_17_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_18_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_19_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_20_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_21_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_22_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_23_brownout : 1;
+};
+
+/**
+ * Signals in message Status4.
+ *
+ * Periodic status frame 4
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PDH_status4_t {
+ /**
+ * Range: 0..4095 (0..31.9921875 V)
+ * Scale: 0.0078125
+ * Offset: 0
+ */
+ uint16_t v_bus : 12;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t system_enable : 1;
+
+ /**
+ * Range: 0..7 (0..7 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t rsvd0 : 3;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t rsvd1 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t can_warning : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t hardware_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sw_state : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t rsvd2 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_can_warning : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_can_bus_off : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_hardware_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_firmware_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_ch20_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_ch21_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_ch22_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_ch23_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_has_reset : 1;
+
+ /**
+ * Range: 0..255 (0..510 A)
+ * Scale: 2
+ * Offset: 0
+ */
+ uint8_t total_current : 8;
+};
+
+/**
+ * Signals in message ClearFaults.
+ *
+ * Clear sticky faults on the device
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PDH_clear_faults_t {
+ /**
+ * Dummy signal in empty message.
+ */
+ uint8_t dummy;
+};
+
+/**
+ * Signals in message Identify.
+ *
+ * Flash the LED on the device to identify this device
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PDH_identify_t {
+ /**
+ * Dummy signal in empty message.
+ */
+ uint8_t dummy;
+};
+
+/**
+ * Signals in message Version.
+ *
+ * Get the version of the PDH device
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PDH_version_t {
+ /**
+ * Range: 0..255 (0..255 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t firmware_fix : 8;
+
+ /**
+ * Range: 0..255 (0..255 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t firmware_minor : 8;
+
+ /**
+ * Range: 0..255 (0..255 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t firmware_year : 8;
+
+ /**
+ * Range: 0..255 (0..255 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t hardware_code : 8;
+
+ /**
+ * Range: 0..4294967295 (0..4294967295 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint32_t unique_id : 32;
+};
+
+/**
+ * Signals in message ConfigureHRChannel.
+ *
+ * Configure a periodic high-resolution channel frame to send back data for a particular channel. This can be useful for more detailed diagnostics, or even for current based control or monitoring.
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PDH_configure_hr_channel_t {
+ /**
+ * Range: 0..23 (0..23 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel : 8;
+
+ /**
+ * Range: 0..65535 (0..65535 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint16_t period : 16;
+};
+
+/**
+ * Signals in message Enter_Bootloader.
+ *
+ * Enter the REV bootloader from user application
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PDH_enter_bootloader_t {
+ /**
+ * Dummy signal in empty message.
+ */
+ uint8_t dummy;
+};
+
+/**
+ * Pack message SwitchChannelSet.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PDH_switch_channel_set_pack(
+ uint8_t *dst_p,
+ const struct PDH_switch_channel_set_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message SwitchChannelSet.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PDH_switch_channel_set_unpack(
+ struct PDH_switch_channel_set_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_switch_channel_set_output_set_value_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_switch_channel_set_output_set_value_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_switch_channel_set_output_set_value_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_switch_channel_set_use_system_enable_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_switch_channel_set_use_system_enable_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_switch_channel_set_use_system_enable_is_in_range(uint8_t value);
+
+/**
+ * Pack message Status0.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PDH_status0_pack(
+ uint8_t *dst_p,
+ const struct PDH_status0_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message Status0.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PDH_status0_unpack(
+ struct PDH_status0_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status0_channel_0_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status0_channel_0_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status0_channel_0_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status0_channel_1_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status0_channel_1_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status0_channel_1_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status0_channel_2_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status0_channel_2_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status0_channel_2_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status0_channel_0_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status0_channel_0_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status0_channel_0_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status0_channel_1_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status0_channel_1_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status0_channel_1_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status0_channel_3_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status0_channel_3_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status0_channel_3_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status0_channel_4_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status0_channel_4_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status0_channel_4_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status0_channel_5_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status0_channel_5_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status0_channel_5_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status0_channel_2_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status0_channel_2_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status0_channel_2_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status0_channel_3_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status0_channel_3_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status0_channel_3_brownout_is_in_range(uint8_t value);
+
+/**
+ * Pack message Status1.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PDH_status1_pack(
+ uint8_t *dst_p,
+ const struct PDH_status1_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message Status1.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PDH_status1_unpack(
+ struct PDH_status1_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status1_channel_6_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status1_channel_6_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status1_channel_6_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status1_channel_7_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status1_channel_7_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status1_channel_7_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status1_channel_8_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status1_channel_8_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status1_channel_8_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status1_channel_4_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status1_channel_4_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status1_channel_4_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status1_channel_5_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status1_channel_5_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status1_channel_5_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status1_channel_9_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status1_channel_9_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status1_channel_9_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status1_channel_10_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status1_channel_10_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status1_channel_10_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status1_channel_11_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status1_channel_11_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status1_channel_11_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status1_channel_6_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status1_channel_6_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status1_channel_6_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status1_channel_7_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status1_channel_7_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status1_channel_7_brownout_is_in_range(uint8_t value);
+
+/**
+ * Pack message Status2.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PDH_status2_pack(
+ uint8_t *dst_p,
+ const struct PDH_status2_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message Status2.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PDH_status2_unpack(
+ struct PDH_status2_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status2_channel_12_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status2_channel_12_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status2_channel_12_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status2_channel_13_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status2_channel_13_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status2_channel_13_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status2_channel_14_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status2_channel_14_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status2_channel_14_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status2_channel_8_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status2_channel_8_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status2_channel_8_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status2_channel_9_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status2_channel_9_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status2_channel_9_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status2_channel_15_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status2_channel_15_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status2_channel_15_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status2_channel_16_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status2_channel_16_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status2_channel_16_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status2_channel_17_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status2_channel_17_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status2_channel_17_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status2_channel_10_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status2_channel_10_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status2_channel_10_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status2_channel_11_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status2_channel_11_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status2_channel_11_brownout_is_in_range(uint8_t value);
+
+/**
+ * Pack message Status3.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PDH_status3_pack(
+ uint8_t *dst_p,
+ const struct PDH_status3_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message Status3.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PDH_status3_unpack(
+ struct PDH_status3_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status3_channel_18_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_18_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_18_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status3_channel_19_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_19_current_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_19_current_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_12_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_12_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_12_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_13_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_13_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_13_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_14_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_14_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_14_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_15_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_15_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_15_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_20_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_20_current_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_20_current_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_21_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_21_current_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_21_current_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_22_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_22_current_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_22_current_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_23_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_23_current_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_23_current_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_16_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_16_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_16_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_17_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_17_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_17_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_18_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_18_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_18_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_19_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_19_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_19_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_20_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_20_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_20_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_21_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_21_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_21_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_22_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_22_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_22_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status3_channel_23_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status3_channel_23_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status3_channel_23_brownout_is_in_range(uint8_t value);
+
+/**
+ * Pack message Status4.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PDH_status4_pack(
+ uint8_t *dst_p,
+ const struct PDH_status4_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message Status4.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PDH_status4_unpack(
+ struct PDH_status4_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_status4_v_bus_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_v_bus_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_v_bus_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_system_enable_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_system_enable_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_system_enable_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_rsvd0_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_rsvd0_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_rsvd0_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_rsvd1_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_rsvd1_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_rsvd1_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_can_warning_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_can_warning_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_can_warning_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_hardware_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_hardware_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_hardware_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_sw_state_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_sw_state_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_sw_state_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_sticky_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_sticky_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_sticky_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_rsvd2_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_rsvd2_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_rsvd2_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_sticky_can_warning_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_sticky_can_warning_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_sticky_can_warning_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_sticky_can_bus_off_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_sticky_can_bus_off_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_sticky_can_bus_off_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_sticky_hardware_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_sticky_hardware_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_sticky_hardware_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_sticky_firmware_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_sticky_firmware_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_sticky_firmware_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_sticky_ch20_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_sticky_ch20_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_sticky_ch20_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_sticky_ch21_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_sticky_ch21_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_sticky_ch21_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_sticky_ch22_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_sticky_ch22_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_sticky_ch22_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_sticky_ch23_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_sticky_ch23_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_sticky_ch23_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_sticky_has_reset_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_sticky_has_reset_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_sticky_has_reset_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_status4_total_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_status4_total_current_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_status4_total_current_is_in_range(uint8_t value);
+
+/**
+ * Pack message ClearFaults.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PDH_clear_faults_pack(
+ uint8_t *dst_p,
+ const struct PDH_clear_faults_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message ClearFaults.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PDH_clear_faults_unpack(
+ struct PDH_clear_faults_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Pack message Identify.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PDH_identify_pack(
+ uint8_t *dst_p,
+ const struct PDH_identify_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message Identify.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PDH_identify_unpack(
+ struct PDH_identify_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Pack message Version.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PDH_version_pack(
+ uint8_t *dst_p,
+ const struct PDH_version_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message Version.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PDH_version_unpack(
+ struct PDH_version_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_version_firmware_fix_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_version_firmware_fix_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_version_firmware_fix_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_version_firmware_minor_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_version_firmware_minor_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_version_firmware_minor_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_version_firmware_year_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_version_firmware_year_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_version_firmware_year_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_version_hardware_code_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_version_hardware_code_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_version_hardware_code_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint32_t PDH_version_unique_id_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_version_unique_id_decode(uint32_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_version_unique_id_is_in_range(uint32_t value);
+
+/**
+ * Pack message ConfigureHRChannel.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PDH_configure_hr_channel_pack(
+ uint8_t *dst_p,
+ const struct PDH_configure_hr_channel_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message ConfigureHRChannel.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PDH_configure_hr_channel_unpack(
+ struct PDH_configure_hr_channel_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PDH_configure_hr_channel_channel_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_configure_hr_channel_channel_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_configure_hr_channel_channel_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PDH_configure_hr_channel_period_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PDH_configure_hr_channel_period_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PDH_configure_hr_channel_period_is_in_range(uint16_t value);
+
+/**
+ * Pack message Enter_Bootloader.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PDH_enter_bootloader_pack(
+ uint8_t *dst_p,
+ const struct PDH_enter_bootloader_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message Enter_Bootloader.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PDH_enter_bootloader_unpack(
+ struct PDH_enter_bootloader_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/hal/src/main/native/athena/rev/PHFrames.cpp b/hal/src/main/native/athena/rev/PHFrames.cpp
new file mode 100644
index 0000000..e7f77e0
--- /dev/null
+++ b/hal/src/main/native/athena/rev/PHFrames.cpp
@@ -0,0 +1,1720 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Erik Moqvist
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * This file was generated by cantools version
+ */
+
+#include <string.h>
+
+#include "PHFrames.h"
+
+static inline uint8_t pack_left_shift_u8(
+ uint8_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint8_t)((uint8_t)(value << shift) & mask);
+}
+
+static inline uint8_t pack_left_shift_u16(
+ uint16_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint8_t)((uint8_t)(value << shift) & mask);
+}
+
+static inline uint8_t pack_right_shift_u16(
+ uint16_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint8_t)((uint8_t)(value >> shift) & mask);
+}
+
+static inline uint16_t unpack_left_shift_u16(
+ uint8_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint16_t)((uint16_t)(value & mask) << shift);
+}
+
+static inline uint8_t unpack_right_shift_u8(
+ uint8_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint8_t)((uint8_t)(value & mask) >> shift);
+}
+
+static inline uint16_t unpack_right_shift_u16(
+ uint8_t value,
+ uint8_t shift,
+ uint8_t mask)
+{
+ return (uint16_t)((uint16_t)(value & mask) >> shift);
+}
+
+int PH_set_all_pack(
+ uint8_t *dst_p,
+ const struct PH_set_all_t *src_p,
+ size_t size)
+{
+ if (size < 4u) {
+ return (-EINVAL);
+ }
+
+ memset(&dst_p[0], 0, 4);
+
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_0, 0u, 0x03u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_1, 2u, 0x0cu);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_2, 4u, 0x30u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_3, 6u, 0xc0u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_4, 0u, 0x03u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_5, 2u, 0x0cu);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_6, 4u, 0x30u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_7, 6u, 0xc0u);
+ dst_p[2] |= pack_left_shift_u8(src_p->channel_8, 0u, 0x03u);
+ dst_p[2] |= pack_left_shift_u8(src_p->channel_9, 2u, 0x0cu);
+ dst_p[2] |= pack_left_shift_u8(src_p->channel_10, 4u, 0x30u);
+ dst_p[2] |= pack_left_shift_u8(src_p->channel_11, 6u, 0xc0u);
+ dst_p[3] |= pack_left_shift_u8(src_p->channel_12, 0u, 0x03u);
+ dst_p[3] |= pack_left_shift_u8(src_p->channel_13, 2u, 0x0cu);
+ dst_p[3] |= pack_left_shift_u8(src_p->channel_14, 4u, 0x30u);
+ dst_p[3] |= pack_left_shift_u8(src_p->channel_15, 6u, 0xc0u);
+
+ return (4);
+}
+
+int PH_set_all_unpack(
+ struct PH_set_all_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ if (size < 4u) {
+ return (-EINVAL);
+ }
+
+ dst_p->channel_0 = unpack_right_shift_u8(src_p[0], 0u, 0x03u);
+ dst_p->channel_1 = unpack_right_shift_u8(src_p[0], 2u, 0x0cu);
+ dst_p->channel_2 = unpack_right_shift_u8(src_p[0], 4u, 0x30u);
+ dst_p->channel_3 = unpack_right_shift_u8(src_p[0], 6u, 0xc0u);
+ dst_p->channel_4 = unpack_right_shift_u8(src_p[1], 0u, 0x03u);
+ dst_p->channel_5 = unpack_right_shift_u8(src_p[1], 2u, 0x0cu);
+ dst_p->channel_6 = unpack_right_shift_u8(src_p[1], 4u, 0x30u);
+ dst_p->channel_7 = unpack_right_shift_u8(src_p[1], 6u, 0xc0u);
+ dst_p->channel_8 = unpack_right_shift_u8(src_p[2], 0u, 0x03u);
+ dst_p->channel_9 = unpack_right_shift_u8(src_p[2], 2u, 0x0cu);
+ dst_p->channel_10 = unpack_right_shift_u8(src_p[2], 4u, 0x30u);
+ dst_p->channel_11 = unpack_right_shift_u8(src_p[2], 6u, 0xc0u);
+ dst_p->channel_12 = unpack_right_shift_u8(src_p[3], 0u, 0x03u);
+ dst_p->channel_13 = unpack_right_shift_u8(src_p[3], 2u, 0x0cu);
+ dst_p->channel_14 = unpack_right_shift_u8(src_p[3], 4u, 0x30u);
+ dst_p->channel_15 = unpack_right_shift_u8(src_p[3], 6u, 0xc0u);
+
+ return (0);
+}
+
+uint8_t PH_set_all_channel_0_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_0_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_0_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_1_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_1_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_1_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_2_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_2_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_2_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_3_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_3_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_3_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_4_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_4_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_4_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_5_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_5_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_5_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_6_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_6_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_6_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_7_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_7_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_7_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_8_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_8_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_8_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_9_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_9_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_9_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_10_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_10_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_10_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_11_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_11_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_11_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_12_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_12_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_12_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_13_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_13_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_13_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_14_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_14_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_14_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+uint8_t PH_set_all_channel_15_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_set_all_channel_15_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_set_all_channel_15_is_in_range(uint8_t value)
+{
+ return (value <= 3u);
+}
+
+int PH_pulse_once_pack(
+ uint8_t *dst_p,
+ const struct PH_pulse_once_t *src_p,
+ size_t size)
+{
+ if (size < 4u) {
+ return (-EINVAL);
+ }
+
+ memset(&dst_p[0], 0, 4);
+
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_0, 0u, 0x01u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_1, 1u, 0x02u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_2, 2u, 0x04u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_3, 3u, 0x08u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_4, 4u, 0x10u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_5, 5u, 0x20u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_6, 6u, 0x40u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_7, 7u, 0x80u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_8, 0u, 0x01u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_9, 1u, 0x02u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_10, 2u, 0x04u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_11, 3u, 0x08u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_12, 4u, 0x10u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_13, 5u, 0x20u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_14, 6u, 0x40u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_15, 7u, 0x80u);
+ dst_p[2] |= pack_left_shift_u16(src_p->pulse_length_ms, 0u, 0xffu);
+ dst_p[3] |= pack_right_shift_u16(src_p->pulse_length_ms, 8u, 0xffu);
+
+ return (4);
+}
+
+int PH_pulse_once_unpack(
+ struct PH_pulse_once_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ if (size < 4u) {
+ return (-EINVAL);
+ }
+
+ dst_p->channel_0 = unpack_right_shift_u8(src_p[0], 0u, 0x01u);
+ dst_p->channel_1 = unpack_right_shift_u8(src_p[0], 1u, 0x02u);
+ dst_p->channel_2 = unpack_right_shift_u8(src_p[0], 2u, 0x04u);
+ dst_p->channel_3 = unpack_right_shift_u8(src_p[0], 3u, 0x08u);
+ dst_p->channel_4 = unpack_right_shift_u8(src_p[0], 4u, 0x10u);
+ dst_p->channel_5 = unpack_right_shift_u8(src_p[0], 5u, 0x20u);
+ dst_p->channel_6 = unpack_right_shift_u8(src_p[0], 6u, 0x40u);
+ dst_p->channel_7 = unpack_right_shift_u8(src_p[0], 7u, 0x80u);
+ dst_p->channel_8 = unpack_right_shift_u8(src_p[1], 0u, 0x01u);
+ dst_p->channel_9 = unpack_right_shift_u8(src_p[1], 1u, 0x02u);
+ dst_p->channel_10 = unpack_right_shift_u8(src_p[1], 2u, 0x04u);
+ dst_p->channel_11 = unpack_right_shift_u8(src_p[1], 3u, 0x08u);
+ dst_p->channel_12 = unpack_right_shift_u8(src_p[1], 4u, 0x10u);
+ dst_p->channel_13 = unpack_right_shift_u8(src_p[1], 5u, 0x20u);
+ dst_p->channel_14 = unpack_right_shift_u8(src_p[1], 6u, 0x40u);
+ dst_p->channel_15 = unpack_right_shift_u8(src_p[1], 7u, 0x80u);
+ dst_p->pulse_length_ms = unpack_right_shift_u16(src_p[2], 0u, 0xffu);
+ dst_p->pulse_length_ms |= unpack_left_shift_u16(src_p[3], 8u, 0xffu);
+
+ return (0);
+}
+
+uint8_t PH_pulse_once_channel_0_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_0_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_0_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_1_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_1_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_1_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_2_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_2_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_2_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_3_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_3_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_3_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_4_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_4_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_4_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_5_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_5_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_5_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_6_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_6_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_6_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_7_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_7_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_7_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_8_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_8_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_8_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_9_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_9_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_9_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_10_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_10_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_10_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_11_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_11_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_11_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_12_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_12_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_12_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_13_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_13_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_13_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_14_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_14_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_14_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_pulse_once_channel_15_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_pulse_once_channel_15_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_channel_15_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint16_t PH_pulse_once_pulse_length_ms_encode(double value)
+{
+ return (uint16_t)(value);
+}
+
+double PH_pulse_once_pulse_length_ms_decode(uint16_t value)
+{
+ return ((double)value);
+}
+
+bool PH_pulse_once_pulse_length_ms_is_in_range(uint16_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+int PH_status0_pack(
+ uint8_t *dst_p,
+ const struct PH_status0_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ memset(&dst_p[0], 0, 8);
+
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_0, 0u, 0x01u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_1, 1u, 0x02u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_2, 2u, 0x04u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_3, 3u, 0x08u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_4, 4u, 0x10u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_5, 5u, 0x20u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_6, 6u, 0x40u);
+ dst_p[0] |= pack_left_shift_u8(src_p->channel_7, 7u, 0x80u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_8, 0u, 0x01u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_9, 1u, 0x02u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_10, 2u, 0x04u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_11, 3u, 0x08u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_12, 4u, 0x10u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_13, 5u, 0x20u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_14, 6u, 0x40u);
+ dst_p[1] |= pack_left_shift_u8(src_p->channel_15, 7u, 0x80u);
+ dst_p[2] |= pack_left_shift_u8(src_p->analog_0, 0u, 0xffu);
+ dst_p[3] |= pack_left_shift_u8(src_p->analog_1, 0u, 0xffu);
+ dst_p[4] |= pack_left_shift_u8(src_p->digital_sensor, 0u, 0x01u);
+ dst_p[4] |= pack_left_shift_u8(src_p->brownout, 1u, 0x02u);
+ dst_p[4] |= pack_left_shift_u8(src_p->compressor_oc, 2u, 0x04u);
+ dst_p[4] |= pack_left_shift_u8(src_p->compressor_open, 3u, 0x08u);
+ dst_p[4] |= pack_left_shift_u8(src_p->solenoid_oc, 4u, 0x10u);
+ dst_p[4] |= pack_left_shift_u8(src_p->can_warning, 5u, 0x20u);
+ dst_p[4] |= pack_left_shift_u8(src_p->hardware_fault, 6u, 0x40u);
+ dst_p[5] |= pack_left_shift_u8(src_p->channel_0_fault, 0u, 0x01u);
+ dst_p[5] |= pack_left_shift_u8(src_p->channel_1_fault, 1u, 0x02u);
+ dst_p[5] |= pack_left_shift_u8(src_p->channel_2_fault, 2u, 0x04u);
+ dst_p[5] |= pack_left_shift_u8(src_p->channel_3_fault, 3u, 0x08u);
+ dst_p[5] |= pack_left_shift_u8(src_p->channel_4_fault, 4u, 0x10u);
+ dst_p[5] |= pack_left_shift_u8(src_p->channel_5_fault, 5u, 0x20u);
+ dst_p[5] |= pack_left_shift_u8(src_p->channel_6_fault, 6u, 0x40u);
+ dst_p[5] |= pack_left_shift_u8(src_p->channel_7_fault, 7u, 0x80u);
+ dst_p[6] |= pack_left_shift_u8(src_p->channel_8_fault, 0u, 0x01u);
+ dst_p[6] |= pack_left_shift_u8(src_p->channel_9_fault, 1u, 0x02u);
+ dst_p[6] |= pack_left_shift_u8(src_p->channel_10_fault, 2u, 0x04u);
+ dst_p[6] |= pack_left_shift_u8(src_p->channel_11_fault, 3u, 0x08u);
+ dst_p[6] |= pack_left_shift_u8(src_p->channel_12_fault, 4u, 0x10u);
+ dst_p[6] |= pack_left_shift_u8(src_p->channel_13_fault, 5u, 0x20u);
+ dst_p[6] |= pack_left_shift_u8(src_p->channel_14_fault, 6u, 0x40u);
+ dst_p[6] |= pack_left_shift_u8(src_p->channel_15_fault, 7u, 0x80u);
+ dst_p[7] |= pack_left_shift_u8(src_p->compressor_on, 0u, 0x01u);
+ dst_p[7] |= pack_left_shift_u8(src_p->system_enabled, 1u, 0x02u);
+
+ return (8);
+}
+
+int PH_status0_unpack(
+ struct PH_status0_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ dst_p->channel_0 = unpack_right_shift_u8(src_p[0], 0u, 0x01u);
+ dst_p->channel_1 = unpack_right_shift_u8(src_p[0], 1u, 0x02u);
+ dst_p->channel_2 = unpack_right_shift_u8(src_p[0], 2u, 0x04u);
+ dst_p->channel_3 = unpack_right_shift_u8(src_p[0], 3u, 0x08u);
+ dst_p->channel_4 = unpack_right_shift_u8(src_p[0], 4u, 0x10u);
+ dst_p->channel_5 = unpack_right_shift_u8(src_p[0], 5u, 0x20u);
+ dst_p->channel_6 = unpack_right_shift_u8(src_p[0], 6u, 0x40u);
+ dst_p->channel_7 = unpack_right_shift_u8(src_p[0], 7u, 0x80u);
+ dst_p->channel_8 = unpack_right_shift_u8(src_p[1], 0u, 0x01u);
+ dst_p->channel_9 = unpack_right_shift_u8(src_p[1], 1u, 0x02u);
+ dst_p->channel_10 = unpack_right_shift_u8(src_p[1], 2u, 0x04u);
+ dst_p->channel_11 = unpack_right_shift_u8(src_p[1], 3u, 0x08u);
+ dst_p->channel_12 = unpack_right_shift_u8(src_p[1], 4u, 0x10u);
+ dst_p->channel_13 = unpack_right_shift_u8(src_p[1], 5u, 0x20u);
+ dst_p->channel_14 = unpack_right_shift_u8(src_p[1], 6u, 0x40u);
+ dst_p->channel_15 = unpack_right_shift_u8(src_p[1], 7u, 0x80u);
+ dst_p->analog_0 = unpack_right_shift_u8(src_p[2], 0u, 0xffu);
+ dst_p->analog_1 = unpack_right_shift_u8(src_p[3], 0u, 0xffu);
+ dst_p->digital_sensor = unpack_right_shift_u8(src_p[4], 0u, 0x01u);
+ dst_p->brownout = unpack_right_shift_u8(src_p[4], 1u, 0x02u);
+ dst_p->compressor_oc = unpack_right_shift_u8(src_p[4], 2u, 0x04u);
+ dst_p->compressor_open = unpack_right_shift_u8(src_p[4], 3u, 0x08u);
+ dst_p->solenoid_oc = unpack_right_shift_u8(src_p[4], 4u, 0x10u);
+ dst_p->can_warning = unpack_right_shift_u8(src_p[4], 5u, 0x20u);
+ dst_p->hardware_fault = unpack_right_shift_u8(src_p[4], 6u, 0x40u);
+ dst_p->channel_0_fault = unpack_right_shift_u8(src_p[5], 0u, 0x01u);
+ dst_p->channel_1_fault = unpack_right_shift_u8(src_p[5], 1u, 0x02u);
+ dst_p->channel_2_fault = unpack_right_shift_u8(src_p[5], 2u, 0x04u);
+ dst_p->channel_3_fault = unpack_right_shift_u8(src_p[5], 3u, 0x08u);
+ dst_p->channel_4_fault = unpack_right_shift_u8(src_p[5], 4u, 0x10u);
+ dst_p->channel_5_fault = unpack_right_shift_u8(src_p[5], 5u, 0x20u);
+ dst_p->channel_6_fault = unpack_right_shift_u8(src_p[5], 6u, 0x40u);
+ dst_p->channel_7_fault = unpack_right_shift_u8(src_p[5], 7u, 0x80u);
+ dst_p->channel_8_fault = unpack_right_shift_u8(src_p[6], 0u, 0x01u);
+ dst_p->channel_9_fault = unpack_right_shift_u8(src_p[6], 1u, 0x02u);
+ dst_p->channel_10_fault = unpack_right_shift_u8(src_p[6], 2u, 0x04u);
+ dst_p->channel_11_fault = unpack_right_shift_u8(src_p[6], 3u, 0x08u);
+ dst_p->channel_12_fault = unpack_right_shift_u8(src_p[6], 4u, 0x10u);
+ dst_p->channel_13_fault = unpack_right_shift_u8(src_p[6], 5u, 0x20u);
+ dst_p->channel_14_fault = unpack_right_shift_u8(src_p[6], 6u, 0x40u);
+ dst_p->channel_15_fault = unpack_right_shift_u8(src_p[6], 7u, 0x80u);
+ dst_p->compressor_on = unpack_right_shift_u8(src_p[7], 0u, 0x01u);
+ dst_p->system_enabled = unpack_right_shift_u8(src_p[7], 1u, 0x02u);
+
+ return (0);
+}
+
+uint8_t PH_status0_channel_0_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_0_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_0_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_1_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_1_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_1_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_2_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_2_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_2_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_3_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_3_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_3_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_4_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_4_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_4_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_5_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_5_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_5_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_6_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_6_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_6_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_7_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_7_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_7_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_8_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_8_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_8_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_9_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_9_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_9_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_10_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_10_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_10_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_11_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_11_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_11_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_12_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_12_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_12_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_13_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_13_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_13_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_14_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_14_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_14_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_15_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_15_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_15_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_analog_0_encode(double value)
+{
+ return (uint8_t)(value / 0.01961);
+}
+
+double PH_status0_analog_0_decode(uint8_t value)
+{
+ return ((double)value * 0.01961);
+}
+
+bool PH_status0_analog_0_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+uint8_t PH_status0_analog_1_encode(double value)
+{
+ return (uint8_t)(value / 0.01961);
+}
+
+double PH_status0_analog_1_decode(uint8_t value)
+{
+ return ((double)value * 0.01961);
+}
+
+bool PH_status0_analog_1_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+uint8_t PH_status0_digital_sensor_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_digital_sensor_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_digital_sensor_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_compressor_oc_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_compressor_oc_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_compressor_oc_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_compressor_open_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_compressor_open_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_compressor_open_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_solenoid_oc_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_solenoid_oc_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_solenoid_oc_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_can_warning_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_can_warning_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_can_warning_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_hardware_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_hardware_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_hardware_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_0_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_0_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_0_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_1_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_1_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_1_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_2_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_2_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_2_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_3_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_3_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_3_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_4_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_4_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_4_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_5_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_5_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_5_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_6_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_6_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_6_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_7_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_7_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_7_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_8_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_8_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_8_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_9_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_9_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_9_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_10_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_10_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_10_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_11_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_11_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_11_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_12_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_12_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_12_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_13_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_13_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_13_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_14_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_14_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_14_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_channel_15_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_channel_15_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_channel_15_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_compressor_on_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_compressor_on_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_compressor_on_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status0_system_enabled_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status0_system_enabled_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status0_system_enabled_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+int PH_status1_pack(
+ uint8_t *dst_p,
+ const struct PH_status1_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ memset(&dst_p[0], 0, 8);
+
+ dst_p[0] |= pack_left_shift_u8(src_p->v_bus, 0u, 0xffu);
+ dst_p[1] |= pack_left_shift_u16(src_p->solenoid_voltage, 0u, 0xffu);
+ dst_p[2] |= pack_right_shift_u16(src_p->solenoid_voltage, 8u, 0x0fu);
+ dst_p[4] |= pack_left_shift_u8(src_p->compressor_current, 0u, 0xffu);
+ dst_p[5] |= pack_left_shift_u8(src_p->solenoid_current, 0u, 0xffu);
+ dst_p[6] |= pack_left_shift_u8(src_p->sticky_brownout, 0u, 0x01u);
+ dst_p[6] |= pack_left_shift_u8(src_p->sticky_compressor_over_current, 1u, 0x02u);
+ dst_p[6] |= pack_left_shift_u8(src_p->sticky_compressor_not_present, 2u, 0x04u);
+ dst_p[6] |= pack_left_shift_u8(src_p->sticky_solenoid_over_current, 3u, 0x08u);
+ dst_p[6] |= pack_left_shift_u8(src_p->sticky_can_warning, 4u, 0x10u);
+ dst_p[6] |= pack_left_shift_u8(src_p->sticky_can_bus_off, 5u, 0x20u);
+ dst_p[6] |= pack_left_shift_u8(src_p->sticky_hardware_fault, 6u, 0x40u);
+ dst_p[6] |= pack_left_shift_u8(src_p->sticky_firmware_fault, 7u, 0x80u);
+ dst_p[7] |= pack_left_shift_u8(src_p->sticky_has_reset, 0u, 0x01u);
+
+ return (8);
+}
+
+int PH_status1_unpack(
+ struct PH_status1_t *dst_p,
+ const uint8_t *src_p,
+ size_t size)
+{
+ if (size < 8u) {
+ return (-EINVAL);
+ }
+
+ dst_p->v_bus = unpack_right_shift_u8(src_p[0], 0u, 0xffu);
+ dst_p->solenoid_voltage = unpack_right_shift_u16(src_p[1], 0u, 0xffu);
+ dst_p->solenoid_voltage |= unpack_left_shift_u16(src_p[2], 8u, 0x0fu);
+ dst_p->compressor_current = unpack_right_shift_u8(src_p[4], 0u, 0xffu);
+ dst_p->solenoid_current = unpack_right_shift_u8(src_p[5], 0u, 0xffu);
+ dst_p->sticky_brownout = unpack_right_shift_u8(src_p[6], 0u, 0x01u);
+ dst_p->sticky_compressor_over_current = unpack_right_shift_u8(src_p[6], 1u, 0x02u);
+ dst_p->sticky_compressor_not_present = unpack_right_shift_u8(src_p[6], 2u, 0x04u);
+ dst_p->sticky_solenoid_over_current = unpack_right_shift_u8(src_p[6], 3u, 0x08u);
+ dst_p->sticky_can_warning = unpack_right_shift_u8(src_p[6], 4u, 0x10u);
+ dst_p->sticky_can_bus_off = unpack_right_shift_u8(src_p[6], 5u, 0x20u);
+ dst_p->sticky_hardware_fault = unpack_right_shift_u8(src_p[6], 6u, 0x40u);
+ dst_p->sticky_firmware_fault = unpack_right_shift_u8(src_p[6], 7u, 0x80u);
+ dst_p->sticky_has_reset = unpack_right_shift_u8(src_p[7], 0u, 0x01u);
+
+ return (0);
+}
+
+uint8_t PH_status1_v_bus_encode(double value)
+{
+ return (uint8_t)((value - 4.0) / 0.0625);
+}
+
+double PH_status1_v_bus_decode(uint8_t value)
+{
+ return (((double)value * 0.0625) + 4.0);
+}
+
+bool PH_status1_v_bus_is_in_range(uint8_t value)
+{
+ return (value <= 192u);
+}
+
+uint16_t PH_status1_solenoid_voltage_encode(double value)
+{
+ return (uint16_t)(value / 0.0078125);
+}
+
+double PH_status1_solenoid_voltage_decode(uint16_t value)
+{
+ return ((double)value * 0.0078125);
+}
+
+bool PH_status1_solenoid_voltage_is_in_range(uint16_t value)
+{
+ return (value <= 4096u);
+}
+
+uint8_t PH_status1_compressor_current_encode(double value)
+{
+ return (uint8_t)(value / 0.125);
+}
+
+double PH_status1_compressor_current_decode(uint8_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PH_status1_compressor_current_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+uint8_t PH_status1_solenoid_current_encode(double value)
+{
+ return (uint8_t)(value / 0.125);
+}
+
+double PH_status1_solenoid_current_decode(uint8_t value)
+{
+ return ((double)value * 0.125);
+}
+
+bool PH_status1_solenoid_current_is_in_range(uint8_t value)
+{
+ (void)value;
+
+ return (true);
+}
+
+uint8_t PH_status1_sticky_brownout_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status1_sticky_brownout_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status1_sticky_brownout_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status1_sticky_compressor_over_current_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status1_sticky_compressor_over_current_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status1_sticky_compressor_over_current_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status1_sticky_compressor_not_present_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status1_sticky_compressor_not_present_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status1_sticky_compressor_not_present_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status1_sticky_solenoid_over_current_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status1_sticky_solenoid_over_current_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status1_sticky_solenoid_over_current_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status1_sticky_can_warning_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status1_sticky_can_warning_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status1_sticky_can_warning_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status1_sticky_can_bus_off_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status1_sticky_can_bus_off_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status1_sticky_can_bus_off_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status1_sticky_hardware_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status1_sticky_hardware_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status1_sticky_hardware_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status1_sticky_firmware_fault_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status1_sticky_firmware_fault_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status1_sticky_firmware_fault_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
+
+uint8_t PH_status1_sticky_has_reset_encode(double value)
+{
+ return (uint8_t)(value);
+}
+
+double PH_status1_sticky_has_reset_decode(uint8_t value)
+{
+ return ((double)value);
+}
+
+bool PH_status1_sticky_has_reset_is_in_range(uint8_t value)
+{
+ return (value <= 1u);
+}
diff --git a/hal/src/main/native/athena/rev/PHFrames.h b/hal/src/main/native/athena/rev/PHFrames.h
new file mode 100644
index 0000000..295be0a
--- /dev/null
+++ b/hal/src/main/native/athena/rev/PHFrames.h
@@ -0,0 +1,3249 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Erik Moqvist
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * This file was generated by cantools version
+ */
+
+#ifndef PH_H
+#define PH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifndef EINVAL
+# define EINVAL 22
+#endif
+
+/* Frame ids. */
+#define PH_SET_ALL_FRAME_ID (0x9050c00u)
+#define PH_PULSE_ONCE_FRAME_ID (0x9050c40u)
+#define PH_STATUS0_FRAME_ID (0x9051800u)
+#define PH_STATUS1_FRAME_ID (0x9051840u)
+
+/* Frame lengths in bytes. */
+#define PH_SET_ALL_LENGTH (4u)
+#define PH_PULSE_ONCE_LENGTH (4u)
+#define PH_STATUS0_LENGTH (8u)
+#define PH_STATUS1_LENGTH (8u)
+
+/* Extended or standard frame types. */
+#define PH_SET_ALL_IS_EXTENDED (1)
+#define PH_PULSE_ONCE_IS_EXTENDED (1)
+#define PH_STATUS0_IS_EXTENDED (1)
+#define PH_STATUS1_IS_EXTENDED (1)
+
+/* Frame cycle times in milliseconds. */
+
+
+/* Signal choices. */
+
+
+/**
+ * Signals in message SetAll.
+ *
+ * Set state of all channels
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PH_set_all_t {
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_0 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_1 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_2 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_3 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_4 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_5 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_6 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_7 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_8 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_9 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_10 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_11 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_12 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_13 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_14 : 2;
+
+ /**
+ * Range: 0..3 (0..3 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_15 : 2;
+};
+
+/**
+ * Signals in message PulseOnce.
+ *
+ * Pulse selected channels once
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PH_pulse_once_t {
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_0 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_1 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_2 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_3 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_4 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_5 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_6 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_7 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_8 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_9 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_10 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_11 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_12 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_13 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_14 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_15 : 1;
+
+ /**
+ * Range: 0..65535 (0..65535 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint16_t pulse_length_ms : 16;
+};
+
+/**
+ * Signals in message Status0.
+ *
+ * Periodic status frame 0
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PH_status0_t {
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_0 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_1 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_2 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_3 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_4 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_5 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_6 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_7 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_8 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_9 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_10 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_11 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_12 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_13 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_14 : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_15 : 1;
+
+ /**
+ * Range: 0..255 (0..5.00055 V)
+ * Scale: 0.01961
+ * Offset: 0
+ */
+ uint8_t analog_0 : 8;
+
+ /**
+ * Range: 0..255 (0..5.00055 V)
+ * Scale: 0.01961
+ * Offset: 0
+ */
+ uint8_t analog_1 : 8;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t digital_sensor : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t compressor_oc : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t compressor_open : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t solenoid_oc : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t can_warning : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t hardware_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_0_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_1_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_2_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_3_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_4_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_5_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_6_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_7_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_8_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_9_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_10_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_11_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_12_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_13_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_14_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t channel_15_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t compressor_on : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t system_enabled : 1;
+};
+
+/**
+ * Signals in message Status1.
+ *
+ * Periodic status frame 1
+ *
+ * All signal values are as on the CAN bus.
+ */
+struct PH_status1_t {
+ /**
+ * Range: 0..192 (4..16 V)
+ * Scale: 0.0625
+ * Offset: 4
+ */
+ uint8_t v_bus : 8;
+
+ /**
+ * Range: 0..4096 (0..32 V)
+ * Scale: 0.0078125
+ * Offset: 0
+ */
+ uint16_t solenoid_voltage : 12;
+
+ /**
+ * Range: 0..256 (0..32 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint8_t compressor_current : 8;
+
+ /**
+ * Range: 0..256 (0..32 A)
+ * Scale: 0.125
+ * Offset: 0
+ */
+ uint8_t solenoid_current : 8;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_brownout : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_compressor_over_current : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_compressor_not_present : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_solenoid_over_current : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_can_warning : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_can_bus_off : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_hardware_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_firmware_fault : 1;
+
+ /**
+ * Range: 0..1 (0..1 -)
+ * Scale: 1
+ * Offset: 0
+ */
+ uint8_t sticky_has_reset : 1;
+};
+
+/**
+ * Pack message SetAll.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PH_set_all_pack(
+ uint8_t *dst_p,
+ const struct PH_set_all_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message SetAll.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PH_set_all_unpack(
+ struct PH_set_all_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_0_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_0_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_0_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_1_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_1_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_1_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_2_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_2_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_2_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_3_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_3_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_3_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_4_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_4_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_4_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_5_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_5_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_5_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_6_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_6_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_6_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_7_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_7_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_7_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_8_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_8_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_8_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_9_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_9_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_9_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_10_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_10_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_10_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_11_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_11_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_11_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_12_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_12_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_12_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_13_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_13_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_13_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_14_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_14_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_14_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_set_all_channel_15_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_set_all_channel_15_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_set_all_channel_15_is_in_range(uint8_t value);
+
+/**
+ * Pack message PulseOnce.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PH_pulse_once_pack(
+ uint8_t *dst_p,
+ const struct PH_pulse_once_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message PulseOnce.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PH_pulse_once_unpack(
+ struct PH_pulse_once_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_0_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_0_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_0_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_1_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_1_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_1_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_2_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_2_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_2_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_3_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_3_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_3_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_4_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_4_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_4_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_5_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_5_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_5_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_6_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_6_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_6_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_7_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_7_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_7_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_8_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_8_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_8_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_9_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_9_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_9_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_10_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_10_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_10_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_11_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_11_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_11_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_12_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_12_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_12_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_13_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_13_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_13_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_14_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_14_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_14_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_pulse_once_channel_15_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_channel_15_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_channel_15_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PH_pulse_once_pulse_length_ms_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_pulse_once_pulse_length_ms_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_pulse_once_pulse_length_ms_is_in_range(uint16_t value);
+
+/**
+ * Pack message Status0.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PH_status0_pack(
+ uint8_t *dst_p,
+ const struct PH_status0_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message Status0.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PH_status0_unpack(
+ struct PH_status0_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_0_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_0_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_0_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_1_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_1_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_1_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_2_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_2_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_2_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_3_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_3_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_3_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_4_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_4_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_4_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_5_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_5_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_5_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_6_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_6_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_6_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_7_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_7_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_7_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_8_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_8_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_8_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_9_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_9_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_9_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_10_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_10_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_10_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_11_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_11_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_11_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_12_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_12_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_12_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_13_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_13_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_13_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_14_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_14_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_14_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_15_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_15_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_15_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_analog_0_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_analog_0_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_analog_0_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_analog_1_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_analog_1_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_analog_1_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_digital_sensor_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_digital_sensor_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_digital_sensor_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_compressor_oc_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_compressor_oc_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_compressor_oc_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_compressor_open_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_compressor_open_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_compressor_open_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_solenoid_oc_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_solenoid_oc_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_solenoid_oc_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_can_warning_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_can_warning_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_can_warning_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_hardware_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_hardware_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_hardware_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_0_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_0_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_0_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_1_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_1_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_1_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_2_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_2_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_2_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_3_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_3_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_3_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_4_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_4_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_4_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_5_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_5_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_5_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_6_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_6_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_6_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_7_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_7_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_7_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_8_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_8_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_8_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_9_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_9_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_9_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_10_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_10_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_10_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_11_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_11_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_11_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_12_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_12_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_12_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_13_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_13_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_13_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_14_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_14_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_14_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_channel_15_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_channel_15_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_channel_15_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_compressor_on_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_compressor_on_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_compressor_on_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status0_system_enabled_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status0_system_enabled_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status0_system_enabled_is_in_range(uint8_t value);
+
+/**
+ * Pack message Status1.
+ *
+ * @param[out] dst_p Buffer to pack the message into.
+ * @param[in] src_p Data to pack.
+ * @param[in] size Size of dst_p.
+ *
+ * @return Size of packed data, or negative error code.
+ */
+int PH_status1_pack(
+ uint8_t *dst_p,
+ const struct PH_status1_t *src_p,
+ size_t size);
+
+/**
+ * Unpack message Status1.
+ *
+ * @param[out] dst_p Object to unpack the message into.
+ * @param[in] src_p Message to unpack.
+ * @param[in] size Size of src_p.
+ *
+ * @return zero(0) or negative error code.
+ */
+int PH_status1_unpack(
+ struct PH_status1_t *dst_p,
+ const uint8_t *src_p,
+ size_t size);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status1_v_bus_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_v_bus_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_v_bus_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint16_t PH_status1_solenoid_voltage_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_solenoid_voltage_decode(uint16_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_solenoid_voltage_is_in_range(uint16_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status1_compressor_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_compressor_current_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_compressor_current_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status1_solenoid_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_solenoid_current_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_solenoid_current_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status1_sticky_brownout_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_sticky_brownout_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_sticky_brownout_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status1_sticky_compressor_over_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_sticky_compressor_over_current_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_sticky_compressor_over_current_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status1_sticky_compressor_not_present_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_sticky_compressor_not_present_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_sticky_compressor_not_present_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status1_sticky_solenoid_over_current_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_sticky_solenoid_over_current_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_sticky_solenoid_over_current_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status1_sticky_can_warning_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_sticky_can_warning_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_sticky_can_warning_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status1_sticky_can_bus_off_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_sticky_can_bus_off_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_sticky_can_bus_off_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status1_sticky_hardware_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_sticky_hardware_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_sticky_hardware_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status1_sticky_firmware_fault_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_sticky_firmware_fault_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_sticky_firmware_fault_is_in_range(uint8_t value);
+
+/**
+ * Encode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to encode.
+ *
+ * @return Encoded signal.
+ */
+uint8_t PH_status1_sticky_has_reset_encode(double value);
+
+/**
+ * Decode given signal by applying scaling and offset.
+ *
+ * @param[in] value Signal to decode.
+ *
+ * @return Decoded signal.
+ */
+double PH_status1_sticky_has_reset_decode(uint8_t value);
+
+/**
+ * Check that given signal is in allowed range.
+ *
+ * @param[in] value Signal to check.
+ *
+ * @return true if in range, false otherwise.
+ */
+bool PH_status1_sticky_has_reset_is_in_range(uint8_t value);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif