Compare commits

...

166 Commits

Author SHA1 Message Date
Thad House
57e9fb33d2 Fixes C++ SendableChooser using invalid temp variable (#945) 2018-02-15 23:00:46 -08:00
Thad House
f5a292dadd Adds TriState JNI entry point (#938)
Also adds missing sim TriState DIO HAL call, and a ToDo for later
2018-02-12 16:05:10 -08:00
Sam Carlberg
77d6c11743 Invert right side motors in MecanumDrive sendable (#933)
This aligns with the current behavior of DifferentialDrive
Fixes shuffleboard#404
2018-02-09 08:30:12 -08:00
Tyler Veness
67f9c9a5b3 Fixed TimedRobot.java hanging if an exception was thrown (#926) 2018-02-04 22:38:19 -08:00
Thad House
f720cbb121 Switches CtreCanNode to use locking and std::chrono for time (#909) 2018-02-01 21:39:06 -08:00
Tyler Veness
64a7e57fe0 Added output normalization to DifferentialDrive::CurvatureDrive() (#924)
This normalizes within -1..1 to avoid clipping and maintain the ratio between
wheel speeds, since that ratio determines the center of rotation.

Fixes #923.
2018-02-01 21:17:04 -08:00
Tyler Veness
5ca00dddbe Added TimedRobot::GetPeriod() (#915)
Fixes #914.
2018-01-27 01:01:15 -08:00
Tyler Veness
120ceb3427 Fix channel reassignments for C++ Joystick twist and throttle axes (#903) 2018-01-26 17:26:10 -08:00
Thad House
5cbafc1382 Updates to image 17 (#913)
These should be binary compatible, so safe to use with image 16.
2018-01-26 17:21:13 -08:00
Thad House
39d1650d51 Fixes double to int to double cast in encoderJNI (#918)
Fixes #916
2018-01-26 17:20:20 -08:00
Thad House
02336fc478 Makes FMS data never be a null string. (#900)
Fixes #895
2018-01-19 23:49:34 -08:00
Thad House
c00848c060 Fixes indexed classed handle resource (#899)
Nothing in WPILib uses it, so it was not tested
2018-01-19 22:31:59 -08:00
Dustin Spicuzza
738a1c015c PIDController: setContinuous should only check input range if continuous is true (#896) 2018-01-19 22:31:08 -08:00
Thad House
48ae6c954a Publishes match specific data and other FMS info to NT (#874)
This is so products like SB can present the current setup.
2018-01-18 23:17:28 -08:00
Thad House
07f70cf784 Fixes control data packet delay (#875)
Because of an expected change in 2018 that didn't happen, we had a race
condition causing a 1 packet delay on all DS values. This fixes that.
2018-01-18 21:54:33 -08:00
sciencewhiz
e4e1eab413 Fix cancel of inner commands in ConditionalCommands (#858) 2018-01-18 20:04:33 -08:00
Nic Hodlofski
0e8ff4663d SpeedControllerGroup: Call set() from pidWrite()
This means pidWrite() now takes m_isInverted into account.
Fixes #887.
2018-01-18 20:03:13 -08:00
HeroCC
54a0a7654a Link to replacements for RobotDrive in JavaDocs (#879)
In smart IDEs, this will allow users to easily view source for these two classes by linking to it
2018-01-11 22:17:33 -08:00
Rohit Vighne
59f938b584 Invert when getting motor speed in SpeedControllerGroup (#886) 2018-01-11 22:16:42 -08:00
sciencewhiz
5513888457 Fix PIDController with Continous and no Input Range set. (#883) 2018-01-11 21:06:25 -08:00
Peter Johnson
02b6615042 RobotController: Make getBatteryVoltage() static. (#869) 2018-01-04 23:12:13 -06:00
Tyler Veness
1f4822f332 Replaced Talon motor controller in DifferentialDrive class docs with Spark (#868) 2018-01-03 20:27:34 -06:00
Peter Johnson
bb38ef5642 DifferentialDrive: Invert right motor in LiveWindow. (#867) 2018-01-02 21:15:15 -06:00
PJ Reiniger
ca36d1dce6 Adding callbacks for notifying when the distance per pulse changes (#861) 2018-01-02 16:53:39 -06:00
Sam Carlberg
ee33296e1f SmartDashboard override .name entry in putData(String, Sendable) (#866)
Fixes #865
2018-01-02 16:39:16 -06:00
Tyler Veness
0ef9803363 Update copyright year to 2018 (#864)
Also fix a few files with incorrect line endings.
2018-01-02 11:20:21 -06:00
Tyler Veness
eedb8910c3 Removed extra newlines from beginning of Java classes (#859)
The content of this PR was generated by styleguide#111.
2018-01-02 11:17:46 -06:00
Sam Carlberg
8346caed9c Move subsystem command metadata to metadata key format (#863) 2018-01-01 17:05:03 -05:00
PJ Reiniger
55b6764d50 Fix bugs in simulation libraries (#853)
Some thing got broken in the past couple of weeks with updates to the
HAL.
2017-12-31 14:37:14 -06:00
Thad House
2c4faee667 Fixes -Og compile and strip binaries (#838) 2017-12-29 22:18:35 -06:00
Jaci R
8d1dee16be Add DriverStation NetworkTables HAL Extension (#829) 2017-12-29 21:55:31 -06:00
Jaci R
76b182600a Add Low Fidelity NetworkTables simulation extension (#823) 2017-12-29 21:54:18 -06:00
sciencewhiz
c647a801ad Add Encoder Index as a child (#857) 2017-12-29 21:48:39 -06:00
sciencewhiz
02131639bc Add Digilent DMC 60 Speed Controller (#855) 2017-12-28 21:42:19 -06:00
Noah Gleason
566e283694 Make setDefaultCommand public (#854) 2017-12-28 12:48:15 -06:00
Peter Johnson
40eb6dfc9b Fix SmartDashboard PutData to hook setters. (#851)
* Fix SmartDashboard PutData to hook setters.

Also update all PutData values in main periodic loop (same as LiveWindow).

* Improve SmartDashboard.putData() repeat call handling.
2017-12-26 18:18:02 -05:00
Dustin Spicuzza
a3e5378d14 SPI: Check for null (#850) 2017-12-25 22:03:22 -06:00
Thad House
691741cfcb Fixes non public static methods in RobotController. (#852) 2017-12-25 20:26:05 -06:00
Thad House
166d9e01bf Add PWMVictorSPX (#842) 2017-12-17 19:59:30 -08:00
Thad House
7eab4371f4 Adds TriState DIO functionality to the HAL (#835)
Adds a function to raw set the DIO direction. Also adds a C++ unsafe
function to enable fast setting of DIO direction.
2017-12-14 00:17:29 -08:00
Peter Johnson
de134a5c60 Add deprecated shims for LiveWindowSendable and NamedSendable. (#834)
This will help prevent old code from breaking (not all cases, but should help).
2017-12-13 23:45:12 -08:00
Peter Johnson
7f074563d0 Add support for automatic SPI transfer engine. (#836)
The SPI Accumulator functions have been moved from HAL to wpilib and rewritten
to use the automatic transfer engine.
2017-12-13 23:41:37 -08:00
Thad House
d3dd586362 Revert "Fixes SPI bad chip select (#818)" (#822)
This is no longer required for image 2018v16.

This reverts commit b42285fddd.
2017-12-12 11:31:20 -08:00
Thad House
9c85105591 Update to image 2018v16 (#833) 2017-12-12 11:03:53 -08:00
Peter Johnson
86ac70a125 Fix wpilibcIntegrationTests RobotController warnings. (#832) 2017-12-11 22:15:29 -08:00
Austin Shalit
3c3a448d47 Deprecate SampleRobot (#472)
Suggest TimedRobot as an alternative.

Remove -Werror from examples to avoid breaking build.
2017-12-11 22:06:01 -08:00
Thad House
8744511f1d Fixes some methods in RobotController not being static. (#831) 2017-12-11 11:48:54 -08:00
Thad House
7729dd972f Fixes JNI symbol check (#830)
setErrorData symbol was missing. However, its been deprecated at the
netcomm level for years, and wasn't exposed in wpilibj. And it would
have been crashing since forever, so safe to remove.
2017-12-11 11:48:39 -08:00
Thad House
8b7aa61091 Adds RobotController class (#828)
Unifies random functionality from other classes
Deprecates all old functions.
2017-12-10 21:52:49 -08:00
Peter Johnson
88a6b4ac38 PIDController::InitSendable(): Use double, not bool for double values. (#827) 2017-12-10 20:58:29 -08:00
Peter Johnson
217b1a2259 VisionRunner: Add stop() function to stop a runForever() loop. (#826)
This was previously possible in Java with Thread.interrupt(), but provide
the same function in both C++ and Java.

Fixes #444.
2017-12-10 20:58:14 -08:00
Thad House
d2e7a90f41 Removes statics from hal sim (#825)
Based off of #824, the equivelent in sim.
2017-12-10 19:38:53 -08:00
Thad House
8bd48d6c34 Switches HAL to manual instead of static initialization (#824)
Only athena.

Will fix a whole lot of init issues.
2017-12-10 18:02:07 -08:00
Thad House
1fa0adb091 Removes MSVC and GCC old version workarounds (#821) 2017-12-08 23:40:35 -08:00
Thad House
f615e68a43 Require GCC 5 for wpilib build (#820)
Will help in season with teams not upgrading their GCC. Will have a
better error message.
2017-12-08 22:48:01 -08:00
Thad House
aa4f0ef4f8 Start using the new FRC compiler define (#797)
Remove all definitions from the MockData headers when in simulation mode.
Add a constexpr IsReal and IsSimulation in RobotBase.
2017-12-08 22:47:21 -08:00
Thad House
b42285fddd Fixes SPI bad chip select (#818)
Temporary workaround for 2018v13 image.
2017-12-08 21:42:30 -08:00
Thad House
8106fbdbea Removes custom CONFIG_ATHENA compiler directive (#796)
In roborio GCC 5.5, __FRC_ROBORIO__ has been added directly to the
compiler. So we can instead use that to detect if we are build for the
roborio, and in a much more reliable way.
2017-12-08 21:40:11 -08:00
Tyler Veness
942ba51765 Reclassified NetworkTables headers as "other library" (#775) 2017-12-07 23:34:29 -08:00
PJ Reiniger
33a08d5b34 Add halsim unit tests (#783)
Also adds function that can register all the callbacks at once.
Since all of the callbacks issue a string identifier, it makes it
possible and easy to have one function callback, and differentiate the
path to take based on the string.  Hooking up all the callbacks at once
makes it easier for the simulator developer to know when something was
added to wpilib rather than looking at the commits.
2017-12-07 22:42:20 -08:00
Thad House
4e3af0756d Removes workarounds for issues in image 10 (#816) 2017-12-06 21:20:03 -08:00
Thad House
5078f6c92a Update to image 2018v13 (#815) 2017-12-06 21:02:36 -08:00
Peter Johnson
899892c119 Change Utility to use Twine. 2017-12-05 00:17:56 -08:00
Peter Johnson
54326311ad Use Twine in error checks. 2017-12-05 00:17:56 -08:00
Peter Johnson
fe53dd2f28 Use Twine for error message inputs. 2017-12-05 00:17:56 -08:00
Peter Johnson
ab137abab5 Use llvm::Twine across C++ Command structure. 2017-12-05 00:17:56 -08:00
Peter Johnson
001dedf3b2 SmartDashboard: Use magic static for static initialization. (#812)
It's possible for SmartDashboard functions to be called from static
initializers in user code, so use a magic static to force initialization
order.
2017-12-04 23:50:27 -08:00
Peter Johnson
f9bece2ffb Update LiveWindow to provide continuous telemetry. (#771)
LiveWindow.updateValues() is now called from IterativeRobotBase on every
loop iteration.  Telemetry for all WPILib classes is enabled by default;
it can be disabled for specific classes using LiveWindow.disableTelemetry(),
or all telemetry can be disabled using LiveWindow.disableAllTelemetry().

This necessitated changing the hook methodology into other classes to
be more property-based rather than each class providing multiple functions.
This had the benefit of reducing boilerplate and increasing consistency.

- Remove NamedSendable, add name to Sendable.

- Provide SendableBase abstract class.

- Deprecate LiveWindow addSensor/addActuator interfaces.

- Add LiveWindow support to drive classes.

- Add addChild() helper functions to Subsystem.

- Fix inheritance hierarchy.  Now only sensors inherit from SensorBase.
  Other devices inherit from some combination of SendableBase, ErrorBase, or
  nothing.
2017-12-04 23:28:33 -08:00
Tyler Veness
3befc7015b Make MotorEncoderTest use LinearDigitalFilter's reference overload (#811) 2017-12-04 22:37:06 -08:00
Tyler Veness
de63e1c8a1 Fixed race condition between PIDController enable/disable and PIDWrite() call
To make this work in PIDController.java, the use of synchronized had to be
replaced with ReentrantLock and try-catch blocks. The locking in
PIDController.java was made equivalent to PIDController.cpp and some existing
race conditions in PIDController.java were fixed in the process.

Fixes #30.
2017-12-04 20:42:33 -08:00
Tyler Veness
a76b1aa800 Reduced scope of PIDController's critical sections
m_pidInput and m_pidOutput are considered constant after their construction.
Setting the input range, output range, tolerance, or continuous mode locks the
controller. m_error and m_result are held in temp variables and set at the end
of the calculation.

Getters of P, I, D, F, m_error, m_setpoint, m_result, and m_enabled lock the
critical section. P, I, D, F, and m_setpoint are retrieved at the beginning of
Calculate().

Fixes #40.
2017-12-04 20:42:33 -08:00
Tyler Veness
350b741adc Cleaned up SampleRobot template and added warning about disabling motor safety (#766) 2017-12-04 20:28:31 -08:00
Thad House
64bfdc1a69 Bail out of the integration tests if enable fails (#792)
A failure is much better then an infinite loop.
2017-12-04 20:24:26 -08:00
Tyler Veness
65cc85f68d Add reference constructors/factory methods to LinearDigitalFilter (#810)
Composition is less verbose with references than with smart pointers.
2017-12-04 20:12:06 -08:00
sciencewhiz
6a00dc7976 Re-Add PacGoat java example (#802) 2017-12-04 20:09:02 -08:00
Tyler Veness
e9e407a87d Replace C identifier lists with (void) (#809)
These changes were generated by wpilibsuite/styleguide#106.
2017-12-04 20:05:51 -08:00
Tyler Veness
59c4984ed6 Deprecated internal filter of PID controller (#746)
This was replaced with an external LinearDigitalFilter.
2017-12-04 20:05:02 -08:00
Peter Johnson
b428d1e4b3 Remove CANSpeedController interface. (#806)
CANJaguar is no longer supported, and CANTalon no longer uses this interface.
2017-12-04 20:03:07 -08:00
Thad House
0994364591 Fixes cross module base class statics (#779) 2017-12-03 00:05:05 -08:00
sciencewhiz
0b8d3f0260 Update SampleRobot template to match comments (#768) 2017-12-02 23:28:52 -08:00
sciencewhiz
52eba45c51 Add missing documentation for squaredInputs for RobotDrive (#805) 2017-12-02 22:31:51 -08:00
Thad House
9090a82ef5 Fixes halsim sources and headers zips (#804) 2017-12-02 22:30:54 -08:00
Peter Johnson
2a69a4c7dc Revert #780 (don't kill FRC_NetCommDaemon). (#795)
This commit reverts commit 0f3f5218ad.
2017-12-01 23:47:01 -08:00
Thad House
9d2393f97e Waits 10 seconds between running the C++ and Java test (#798)
Potentially will fix java tests not enabling.
2017-12-01 23:45:49 -08:00
Peter Johnson
dae619b006 Add error reporting to AbstractComsSetup test initialization. (#800) 2017-12-01 23:44:11 -08:00
Thad House
9c06d2878b Update to latest native plugin (#799)
This is what prints warnings to console.
2017-12-01 16:23:30 -08:00
Peter Johnson
e3a2abdf97 HAL_SetDigitalPWMRate(): Use same logic as LabView. (#794) 2017-12-01 10:26:40 -08:00
Peter Johnson
7867e906e9 NidecBrushless: Have disable() call PWM.setDisabled(). (#763)
This provides a way to stop motor operation even if the DIO is disconnected.

Also change Set() to enable the PWM instead of having the constructor do it.

Provide an explicit Enable() call to re-enable after Disable() is called.
This is different from the other motor controllers (which automatically
re-enable when Set() is called) due to the dual-wiring of this motor
controller.

Motor safety results in disabling the motor only until the next Set() call.
2017-12-01 00:43:11 -08:00
Peter Johnson
65a044f633 Fix HAL_CleanNotifier race. (#793)
This race was caused by holding a lock while calling into FRC_ChipObject,
which was waiting for the callback to exit before returning, and our
callback wanted to grab the same lock.
2017-11-30 20:45:40 -08:00
sciencewhiz
cbd08a1e11 Add tests for equivilance of RobotDrive and DifferentialDrive/MecanumDrive (#732)
Add documentation for how to get same results as RobotDrive and improve
RobotDrive documentation
2017-11-29 21:41:00 -08:00
sciencewhiz
e308dd28f3 Fix javadoc link in Solenoid.java (#789) 2017-11-29 21:33:29 -08:00
Thad House
fa0b4428e9 Runs DS enabled loop in process (#785)
Solves mutex issues, and other issues with the existing teststand
software. And simplifies the unit test structure.
2017-11-28 19:12:05 -08:00
Tyler Veness
26a36779a6 Performed cleanup of Timer's free functions (#776)
* GetClock() is now officially deprecated since its comment already informally
  did so and the function just forwards to Timer::GetFPGATimestamp().
* The declaration of GetPPCTimestamp() is missing a definition and has been
  removed.
* std::this_thread::sleep_for() returns immediately when given a negative
  duration, so the check for that was removed from Wait().
2017-11-27 21:59:00 -08:00
Tyler Veness
dfc0656e5c Fix wpilibj FilterOutputTest null pointer exception (#778) 2017-11-27 12:28:25 -08:00
Peter Johnson
0f3f5218ad Kill FRC_NetCommDaemon as well as robot programs. (#780)
Also use flock on Jenkins side to prevent multiple simultaneous runs, instead of using teststand mutex.
2017-11-27 12:24:46 -08:00
Tyler Veness
34c44b7ae9 Improved Drive docs and fix implementation bugs (#774)
I also found some inconsistencies in MecanumDrive and KilloughDrive and fixed
them.

Drive now uses the NED axes convention. Therefore, the positive X axis points
ahead, the positive Y axis points to the right, and the positive Z axis points
down.

Translation in X assumes forward is positive. Translation in Y assumes right is
positive. Rotation rate assumes clockwise is positive. Angles are measured
clockwise from the positive X axis.

Based on the angle origin convention, DrivePolar() for both Mecanum and Killough
needed the normalization removed, sine used to compute the Y component, and
cosine used to compute the X component.

The vector rotation done in DriveCartesian() needs to rotate by a negative angle
instead of positive to undo the robot's rotation. RobotDrive assumed a clockwise
angle and sensors returned counter-clockwise angles, which is why it used a
positive angle for rotation.
2017-11-26 18:36:51 -08:00
sciencewhiz
7a250a1b93 Implement PCM One Shot feature. Fixes artf4731 (#539) 2017-11-26 12:55:21 -08:00
Caleb Smith
a338ee8be0 Add PIDController Wrapping (#601) 2017-11-25 21:15:33 -08:00
sciencewhiz
c9d440f338 Fix Java Compressor test. Make limits same as C++. (#772) 2017-11-24 20:14:36 -08:00
Tyler Veness
a00b2449db Removed unused includes and replaced Ultrasonic's std::set with std::vector (#767) 2017-11-23 20:46:24 -08:00
Tyler Veness
5c659fdcdf Deprecated PIDController::SetTolerance() (#764)
PIDController::SetPercentTolerance() behaves identically to it, so removing
SetTolerance() leaves one obvious way to do absolute or percent tolerance.
2017-11-23 01:21:36 -08:00
Thad House
d36d72bd4f Fixes MotorSafetyHelper locking and race conditions (#762)
Closes #760
2017-11-23 00:36:57 -08:00
sciencewhiz
614093c0c4 Fix documentation for getMatchTime in Timer class to match DriverStation (#761) 2017-11-23 00:19:05 -08:00
PJ Reiniger
12c4418bda Added callbacks for CAN (#757)
Added callback scheme for a pass through to something higher
level.  Since the ID is embedded into the arbitration ID, and some
devices can use different schemes whether it is plugged in through a
device or put into the daisy chain (pigeonImu), I made one "internal
data object" for max reusability.
2017-11-22 19:48:32 -08:00
Caleb Smith
0431cf97ff Cleanup PIDController (#597) 2017-11-22 18:56:35 -08:00
Tyler Veness
ba879f4663 Cleaned up variable names for std::lock_guard and their associated mutexes (#759) 2017-11-22 17:10:21 -08:00
Tyler Veness
96de0b5b11 Variable name fixes (#758) 2017-11-22 17:06:57 -08:00
Tyler Veness
85157a56c3 CircularBuffer now uses an idiomatic interface in C++ and Java (#421) 2017-11-22 17:04:57 -08:00
Tyler Veness
029246ed28 Replaced extra constructors in LinearDigitalFilter with llvm::ArrayRef<> (#755)
llvm::ArrayRef<> replaces both the std::initializer_list<> and std::vector<>
constructor overloads.
2017-11-20 21:23:00 -08:00
sciencewhiz
6377ab774d Allow deprecated warnings for tests (#756) 2017-11-20 21:21:50 -08:00
Tyler Veness
05e581f409 Fixed crash in wpilibj SampleRobot (#753)
robotInit() and HAL.observeUserProgramStarting() should be called in
startCompetition() rather than the constructor.

Fixes #752.
2017-11-19 22:47:39 -08:00
Peter Johnson
c73dd807e1 ErrorBase: Remove last use of sstream and iostream. (#750) 2017-11-19 20:16:42 -08:00
Tyler Veness
7a0dd9baa9 Add return-to-zero test for LinearDigitalFilter moving average (#751)
Ensures LinearDigitalFilter moving average returns to zero after non-zero
values are inserted.

Tests for issue #642
2017-11-19 20:16:09 -08:00
Tyler Veness
11f37683c3 Added constructor to PIDController that takes references instead of pointers (#745) 2017-11-19 19:06:00 -08:00
Tyler Veness
5af0c9c101 Replaced const variables with constexpr (#731) 2017-11-19 19:04:28 -08:00
Tyler Veness
259461aee9 Added PIDController::GetAvgError() back in (#749)
It got removed during the LinearDigitalFilter change (#38) instead of deprecated
by mistake.
2017-11-19 18:23:48 -08:00
Peter Johnson
d214b36786 Change HAL notifier to polling. (#627)
This moves the thread code to the WPILib layer, fixing various potential
races and significantly simplifying the HAL implementation.
2017-11-19 17:58:40 -08:00
Tyler Veness
4a07f0380f PIDController class now uses LinearDigitalFilter for filtering velocity instead of internal queue (#38) 2017-11-19 15:58:30 -08:00
Peter Johnson
7f46b50b21 Unify WPI_Now and HAL_GetFPGATime. (#743)
Depends on wpilibsuite/wpiutil#56.
2017-11-19 12:33:36 -08:00
PJ Reiniger
303c259b89 Simulate ADX* family of accelerometers and gyros (#688) 2017-11-18 12:31:51 -08:00
Thad House
cd1dbb1e3a Adds a const buffer listener (#742)
Replaces need for const_cast in SPI and I2C functions
2017-11-17 10:01:49 -08:00
Peter Johnson
a20474bfc7 Update sensors to not use direct byte buffers. 2017-11-17 09:36:57 -08:00
Peter Johnson
479d0beb5a SerialPort: Use byte[] instead of ByteBuffer in JNI. 2017-11-17 09:36:57 -08:00
Peter Johnson
b93aa176d6 AnalogInput: Remove byte buffer usage. 2017-11-17 09:36:57 -08:00
Peter Johnson
9021b37fd2 I2C: Provide byte[] JNI interfaces.
This avoids a direct byte buffer allocation on every read/write/transaction
on the byte[] variants.

Changes HAL I2C interfaces to use const for dataToSend.
2017-11-17 09:36:57 -08:00
Peter Johnson
6307d41002 SPI: Provide byte[] JNI interfaces.
This avoids a direct byte buffer allocation on every read/write/transaction
for the byte[] variants.

Also change spiGetAccumulatorOutput() to directly set the AccumulatorResult
object, avoiding a ByteBuffer allocation.

Changes HAL SPI interfaces to use const for dataToSend.

Fixes #733.
2017-11-17 09:36:57 -08:00
Peter Johnson
df7c1389de Remove ni-libraries libi2c and libspi. 2017-11-16 23:01:28 -08:00
Peter Johnson
6accc31ee7 HAL: implement I2C and SPI directly instead of using i2clib and spilib.
This reduces library dependencies, improves error handling, and makes
future enhancements easier.
2017-11-16 23:01:28 -08:00
Thad House
f56ec10bcf Only return lower 32 bits of FPGA time (#741)
Works around an NI bug in image 10.
2017-11-16 20:52:50 -08:00
Tyler Veness
e5e6d6a193 Ran formatter based on styleguide#95 (#737) 2017-11-16 01:05:20 -08:00
Tyler Veness
c663d7cd16 Reflowed comments and removed commented out code (#735) 2017-11-16 00:33:51 -08:00
Tyler Veness
1e8d18b328 Upgrade Travis CI Python version to 3.5 (#740) 2017-11-16 00:19:16 -08:00
Peter Johnson
c2d95db3ab Fix PreferencesTest. (#739) 2017-11-15 23:56:17 -08:00
Thad House
dd7563376b Force load OpenCV and cscore libraries on program initialization (#716)
Fixes bugs where Mat's are initialized before anything cscore was
called.
2017-11-14 22:04:53 -08:00
Tyler Veness
14fcf3f2f0 Simplified PIDController integration logic (#645)
A clamp() helper function was written based on C++17's std::clamp().
2017-11-13 22:28:55 -08:00
Peter Johnson
020ee227d2 Move ctre headers to hal/src so they aren't user-visible. (#728)
Also removes ctre_frames.h entirely since it's not used.

Fixes #683.
2017-11-13 22:23:18 -08:00
Peter Johnson
4d559f3856 Use wpi::mutex instead of std::mutex. (#730)
This uses a priority-aware mutex on Linux platforms.

Fixes #729.
2017-11-13 09:51:48 -08:00
Thad House
35d68d2a34 Adds ability to simulate joysticks and event info (#727)
Thanks @pjreiniger for the initiali implementation and work on this.
2017-11-12 19:33:43 -08:00
Peter Johnson
7007725d9f SerialHelper: Check error_code to prevent infinite loop. (#725) 2017-11-11 22:13:59 -08:00
Tyler Veness
0c83cad70c Upgraded clang-format to 5.0 (#431) 2017-11-11 22:09:51 -08:00
sciencewhiz
0001047b8b Add NidecBrushless to WPILib.h (#724) 2017-11-11 16:35:43 -08:00
Thad House
c885251367 Fixes HALSim_Print build to be the standardized pattern (#721)
Now publishes in zips, and with proper artifacts.

The code files just moved, and no changes.
2017-11-10 19:26:33 -08:00
Tyler Veness
42096fac3f Ran formatter (#722) 2017-11-10 18:29:27 -08:00
sciencewhiz
6be9e69d13 Switch Command Templates to TimedRobot (#719) 2017-11-09 20:08:41 -08:00
Thad House
7bbd13d914 Adds match specific calls to Java and C++ (#720)
Uses caching, matching the joystick calls.
2017-11-09 19:59:29 -08:00
Thad House
2225c4fee2 Fixes warnings for casts in sim interrupt functions (#718) 2017-11-09 14:01:24 -08:00
Tyler Veness
7efab4c43a Replaced ternary operators with if statements (#346)
Instances of the ternary operator were replaced with if statements to make the code base more consistent.
2017-11-08 23:44:03 -08:00
Thad House
c8e44256ef Uses NI provided function for SetOccurDataRef rather then importing the symbol ourselves. (#714) 2017-11-08 23:41:16 -08:00
Peter Johnson
f3cd883c5c Add Nidec Brushless motor. (#705) 2017-11-08 23:40:01 -08:00
Thad House
f34c736fb2 Adds warning prints to native library builds (#710)
Can be disabled with -PskipWarningPrints
2017-11-08 23:14:21 -08:00
Tyler Veness
1276489961 Removed uses of deprecated functions (#709) 2017-11-08 21:29:29 -08:00
Tyler Veness
8b2e656bde Fixed Java velocity PID not calculating result when P = 0 (#717) 2017-11-08 21:28:09 -08:00
Thad House
6e9d1f55c6 Updates image to 2018 v10 image (#713) 2017-11-08 11:26:11 -08:00
Thad House
f4dce9e608 Fixes receive size in Java I2C (#715)
Allows underrun, which matches c++ behavior.

Fixes #711
2017-11-07 18:43:23 -08:00
Thad House
b9aabc71b0 Fixes publishing basenames for examples to make combiner script work. (#712) 2017-11-07 14:54:17 -08:00
Jaci R
0d54772362 Add IDEA plugin to root project (#707) 2017-11-05 19:57:53 -08:00
Tyler Veness
faf134a674 C++ examples no longer use deprecated APIs (#703) 2017-11-05 19:39:47 -08:00
Thad House
c24e755409 Fixes java example publishing and xml file (#706) 2017-11-04 10:09:41 -07:00
Thad House
bee9f1cb17 Adds header task to print out all headers (#704)
Will be used to create a generator for IDE's to get include paths.
2017-11-03 22:50:06 -07:00
Tyler Veness
45d48d6b5a Cleaned up C++ examples (#672) 2017-11-03 13:22:56 -07:00
Peter Johnson
6401aa1fde SerialHelper: Use llvm path functions instead of popen. (#702)
This avoids a fork that causes an out-of-memory error in Java.

Depends on wpilibsuite/wpiutil#43
2017-11-03 12:30:56 -07:00
Thad House
6af4940c22 Adds HAL calls for match data from DS (#691) 2017-11-01 21:58:44 -07:00
Sam Carlberg
237b2df82f Add .type metadata to preferences table (#701)
Allows shuffleboard to automatically discover the type, instead of inflexibly hardcoding it
2017-10-30 21:50:49 -07:00
Peter Johnson
a70687aaec Improve error reporting for the new TCP netconsole. (#700)
Fixes #695.
2017-10-30 21:50:14 -07:00
sciencewhiz
fbfe85568b Fix preferences test (#699) 2017-10-29 21:30:50 -07:00
Tyler Veness
595b1df380 Fixed minimum number of joystick axes (#696) 2017-10-29 17:21:50 -07:00
1036 changed files with 21949 additions and 11295 deletions

View File

@@ -5,7 +5,7 @@ AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
@@ -32,12 +32,20 @@ BraceWrapping:
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
@@ -45,7 +53,11 @@ Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeCategories:
- Regex: '^<.*\.h>'
Priority: 1
@@ -53,9 +65,12 @@ IncludeCategories:
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
@@ -64,6 +79,7 @@ NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
@@ -73,7 +89,9 @@ PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false

2
.gitignore vendored
View File

@@ -12,6 +12,8 @@ test-reports
# IntelliJ
*.iml
*.ipr
*.iws
.idea/
# Created by http://www.gitignore.io

View File

@@ -31,6 +31,7 @@ modifiableFileExclude {
includeOtherLibs {
^HAL/
^llvm/
^networktables/
^opencv2/
^support/
}

View File

@@ -1,19 +1,26 @@
sudo: false
sudo: true
dist: trusty
language: java
addons:
apt:
sources:
- deadsnakes
- ubuntu-toolchain-r-test
packages:
- g++-6
- python3
- python3-pip
- clang-format-3.8
- python3.5
before_install:
- sudo sh -c 'echo "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main" > /etc/apt/sources.list.d/llvm.list'
- wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
- sudo apt-get update -q || true
- sudo apt-get install clang-format-5.0 -y
install:
- pip3 install --user wpiformat
- wget https://bootstrap.pypa.io/get-pip.py
- sudo python3.5 get-pip.py
- python3.5 -m pip install --user wpiformat
- mkdir -p $HOME/latest-gcc-symlinks # see travis-ci/travis-ci#3668
- ln -s /usr/bin/g++-6 $HOME/latest-gcc-symlinks/g++
- ln -s /usr/bin/gcc-6 $HOME/latest-gcc-symlinks/gcc
@@ -28,6 +35,6 @@ cache:
- $HOME/.gradle/wrapper/
script:
- wpiformat -y 2017 -clang 3.8
- python3.5 -m wpiformat -y 2018 -clang 5.0
- git --no-pager diff --exit-code HEAD # Ensure formatter made no changes
- ./gradlew --no-daemon --console=plain -PskipAthena :hal:halSimSharedLibrary :wpilibc:wpilibcSharedLibrary :wpilibj:wpilibJNISharedSharedLibrary :wpilibj:jar

View File

@@ -9,13 +9,14 @@ buildscript {
}
}
dependencies {
classpath 'gradle.plugin.edu.wpi.first:native-utils:1.2.12'
classpath 'gradle.plugin.edu.wpi.first:native-utils:1.5.1'
}
}
plugins {
id 'net.ltgt.errorprone' version '0.0.10'
id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '2.0'
id 'idea'
}
ext.licenseFile = file("$rootDir/LICENSE.txt")

View File

@@ -1,21 +1,21 @@
import edu.wpi.first.nativeutils.*
import org.gradle.internal.os.OperatingSystem
def windowsCompilerArgs = ['/EHsc', '/DNOMINMAX', '/D_SCL_SECURE_NO_WARNINGS', '/D_WINSOCK_DEPRECATED_NO_WARNINGS',
'/Zi', '/FS', '/Zc:inline', '/MT']
def windowsCompilerArgs = ['/EHsc', '/DNOMINMAX', '/Zi', '/FS', '/Zc:inline', '/MT']
def windowsReleaseCompilerArgs = ['/O2']
def windowsLinkerArgs = [ '/DEBUG:FULL' ]
def windowsReleaseLinkerArgs = [ '/OPT:REF', '/OPT:ICF' ]
def linuxCompilerArgs = ['-std=c++1y', '-Wformat=2', '-Wall', '-Wextra', '-Werror', '-pedantic', '-Wno-psabi', '-g',
def linuxCompilerArgs = ['-std=c++11', '-Wformat=2', '-Wall', '-Wextra', '-Werror', '-pedantic', '-Wno-psabi', '-g',
'-Wno-unused-parameter', '-fPIC', '-rdynamic', '-Wno-error=deprecated-declarations', '-pthread']
def linuxLinkerArgs = ['-rdynamic', '-pthread']
def linuxReleaseCompilerArgs = ['-O2']
def linuxReleaseCompilerArgs = ['-Og']
def linuxDebugCompilerArgs = ['-O0']
def linux32BitArg = '-m32'
def macCompilerArgs = ['-std=c++11', '-Wall', '-Wextra', '-Werror', '-pedantic-errors', '-fPIC', '-g',
'-Wno-unused-parameter', '-Wno-missing-field-initializers', '-Wno-unused-private-field', '-Wno-unused-const-variable', '-pthread']
'-Wno-unused-parameter', '-Wno-missing-field-initializers', '-Wno-unused-private-field',
'-Wno-unused-const-variable', '-pthread']
def macReleaseCompilerArgs = ['-O2']
def macDebugCompilerArgs = ['-O0']
def mac32BitArg = '-m32'
@@ -147,6 +147,7 @@ if (!project.hasProperty('onlyAthena')) {
linkerArgs << linux32BitArg
debugCompilerArgs = linuxDebugCompilerArgs
releaseCompilerArgs = linuxReleaseCompilerArgs
releaseStripBinaries = true
compilerFamily = 'Gcc'
detectPlatform = linux32IntelPlatformDetect
exclude << 'halAthena'
@@ -159,6 +160,7 @@ if (!project.hasProperty('onlyAthena')) {
linkerArgs = linuxLinkerArgs
debugCompilerArgs = linuxDebugCompilerArgs
releaseCompilerArgs = linuxReleaseCompilerArgs
releaseStripBinaries = true
compilerFamily = 'Gcc'
detectPlatform = linux64IntelPlatformDetect
exclude << 'halAthena'
@@ -173,6 +175,7 @@ if (!project.hasProperty('onlyAthena')) {
linkerArgs << mac32BitArg
debugCompilerArgs = macDebugCompilerArgs
releaseCompilerArgs = macReleaseCompilerArgs
releaseStripBinaries = true
compilerFamily = 'Clang'
detectPlatform = mac32PlatformDetect
exclude << 'halAthena'
@@ -184,56 +187,45 @@ if (!project.hasProperty('onlyAthena')) {
compilerArgs = macCompilerArgs
debugCompilerArgs = macDebugCompilerArgs
releaseCompilerArgs = macReleaseCompilerArgs
releaseStripBinaries = true
compilerFamily = 'Clang'
detectPlatform = mac64PlatformDetect
exclude << 'halAthena'
}
raspbian(CrossBuildConfig) {
architecture = 'raspbian'
}
}
}
if (project.hasProperty('linuxCross')) {
model {
buildConfigs {
linuxArm(CrossBuildConfig) {
architecture = 'nativearm'
operatingSystem = 'linux'
toolChainPrefix = 'arm-linux-gnueabihf-'
compilerArgs = linuxCompilerArgs
linkerArgs = linuxLinkerArgs
debugCompilerArgs = linuxDebugCompilerArgs
releaseCompilerArgs = linuxReleaseCompilerArgs
skipByDefault = true
compilerFamily = 'Gcc'
exclude << 'gmock'
exclude << 'halAthena'
}
armhf(CrossBuildConfig) {
architecture = 'armhf'
operatingSystem = 'linux'
toolChainPrefix = 'arm-linux-gnueabihf-'
compilerArgs = linuxCompilerArgs
linkerArgs = linuxLinkerArgs
debugCompilerArgs = linuxDebugCompilerArgs
releaseCompilerArgs = linuxReleaseCompilerArgs
skipByDefault = true
compilerFamily = 'Gcc'
exclude << 'gmock'
exclude << 'halAthena'
}
aarch(CrossBuildConfig) {
architecture = 'aarch'
operatingSystem = 'linux'
toolChainPrefix = 'aarch-linux-gnu-'
toolChainPrefix = 'PLEASE_PROVIDE_A_COMPILER_NAME'
compilerArgs = linuxCompilerArgs
linkerArgs = linuxLinkerArgs
debugCompilerArgs = linuxDebugCompilerArgs
releaseCompilerArgs = linuxReleaseCompilerArgs
releaseStripBinaries = true
skipByDefault = true
compilerFamily = 'Gcc'
exclude << 'gmock'
exclude << 'halAthena'
}
}
}
} else {
model {
buildConfigs {
linuxArm(BuildConfig) {
architecture = 'arm'
architecture = 'nativearm'
operatingSystem = 'linux'
compilerArgs = linuxCompilerArgs
linkerArgs = linuxLinkerArgs
debugCompilerArgs = linuxDebugCompilerArgs
releaseCompilerArgs = linuxReleaseCompilerArgs
releaseStripBinaries = true
compilerFamily = 'Gcc'
detectPlatform = linuxArmPlatformDetect
exclude << 'halAthena'

View File

@@ -5,17 +5,6 @@ apply plugin: 'edu.wpi.first.NativeUtils'
apply from: '../config.gradle'
ext.addHalCompilerArguments = { binary->
if (binary.targetPlatform.architecture.name == 'athena') {
tasks.withType(CppCompile) {
binary.cppCompiler.args "-DCONFIG_ATHENA"
}
}
tasks.withType(CppCompile) {
binary.cppCompiler.args "-DNAMESPACED_PRIORITY"
}
}
ext.addHalToLinker = { binary->
if (binary.targetPlatform.architecture.name == 'athena') {
binary.lib project: ':hal', library: 'halAthena', linkage: 'shared'
@@ -172,7 +161,6 @@ model {
}
binaries {
all {
project.addHalCompilerArguments(it)
project(':ni-libraries').addNiLibrariesToLinker(it)
}
withType(GoogleTestTestSuiteBinarySpec) {
@@ -202,6 +190,32 @@ model {
}
}
}
getHeaders(Task) {
def list = []
$.components.each {
if (it in NativeLibrarySpec && (it.name == 'halAthena' || it.name == 'halSim')) {
it.sources.each {
it.exportedHeaders.srcDirs.each {
list.add(it)
}
}
it.binaries.each {
it.libs.each {
it.includeRoots.each {
list.add(it)
}
}
}
}
}
list = list.unique(false)
doLast {
list.each {
print "WPIHEADER: "
println it
}
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -19,14 +19,14 @@
using namespace hal;
// The 7-bit I2C address with a 0 "send" bit
static const uint8_t kSendAddress = (0x1c << 1) | 0;
static constexpr uint8_t kSendAddress = (0x1c << 1) | 0;
// The 7-bit I2C address with a 1 "receive" bit
static const uint8_t kReceiveAddress = (0x1c << 1) | 1;
static constexpr uint8_t kReceiveAddress = (0x1c << 1) | 1;
static const uint8_t kControlTxRx = 1;
static const uint8_t kControlStart = 2;
static const uint8_t kControlStop = 4;
static constexpr uint8_t kControlTxRx = 1;
static constexpr uint8_t kControlStart = 2;
static constexpr uint8_t kControlStop = 4;
static std::unique_ptr<tAccel> accel;
static HAL_AccelerometerRange accelerometerRange;
@@ -77,6 +77,12 @@ enum Register {
kReg_OffZ = 0x31
};
namespace hal {
namespace init {
void InitializeAccelerometer() {}
} // namespace init
} // namespace hal
namespace hal {
static void writeRegister(Register reg, uint8_t data);
@@ -91,6 +97,8 @@ static void initializeAccelerometer() {
if (!accel) {
accel.reset(tAccel::create(&status));
accelerometerRange = HAL_AccelerometerRange::HAL_AccelerometerRange_k2G;
// Enable I2C
accel->writeCNFG(1, &status);
@@ -219,7 +227,7 @@ void HAL_SetAccelerometerRange(HAL_AccelerometerRange range) {
*
* This is a floating point value in units of 1 g-force
*/
double HAL_GetAccelerometerX() {
double HAL_GetAccelerometerX(void) {
initializeAccelerometer();
int32_t raw =
@@ -232,7 +240,7 @@ double HAL_GetAccelerometerX() {
*
* This is a floating point value in units of 1 g-force
*/
double HAL_GetAccelerometerY() {
double HAL_GetAccelerometerY(void) {
initializeAccelerometer();
int32_t raw =
@@ -245,7 +253,7 @@ double HAL_GetAccelerometerY() {
*
* This is a floating point value in units of 1 g-force
*/
double HAL_GetAccelerometerZ() {
double HAL_GetAccelerometerZ(void) {
initializeAccelerometer();
int32_t raw =

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -12,6 +12,12 @@
using namespace hal;
namespace hal {
namespace init {
void InitializeAnalogAccumulator() {}
} // namespace init
} // namespace hal
extern "C" {
/**
@@ -22,7 +28,7 @@ extern "C" {
*/
HAL_Bool HAL_IsAccumulatorChannel(HAL_AnalogInputHandle analogPortHandle,
int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
@@ -55,7 +61,7 @@ void HAL_InitAccumulator(HAL_AnalogInputHandle analogPortHandle,
*/
void HAL_ResetAccumulator(HAL_AnalogInputHandle analogPortHandle,
int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -84,7 +90,7 @@ void HAL_ResetAccumulator(HAL_AnalogInputHandle analogPortHandle,
*/
void HAL_SetAccumulatorCenter(HAL_AnalogInputHandle analogPortHandle,
int32_t center, int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -104,7 +110,7 @@ void HAL_SetAccumulatorCenter(HAL_AnalogInputHandle analogPortHandle,
*/
void HAL_SetAccumulatorDeadband(HAL_AnalogInputHandle analogPortHandle,
int32_t deadband, int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -127,7 +133,7 @@ void HAL_SetAccumulatorDeadband(HAL_AnalogInputHandle analogPortHandle,
*/
int64_t HAL_GetAccumulatorValue(HAL_AnalogInputHandle analogPortHandle,
int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -151,7 +157,7 @@ int64_t HAL_GetAccumulatorValue(HAL_AnalogInputHandle analogPortHandle,
*/
int64_t HAL_GetAccumulatorCount(HAL_AnalogInputHandle analogPortHandle,
int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -175,7 +181,7 @@ int64_t HAL_GetAccumulatorCount(HAL_AnalogInputHandle analogPortHandle,
*/
void HAL_GetAccumulatorOutput(HAL_AnalogInputHandle analogPortHandle,
int64_t* value, int64_t* count, int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -34,8 +34,18 @@ static constexpr double kDefaultVoltsPerDegreePerSecond = 0.007;
using namespace hal;
static IndexedHandleResource<HAL_GyroHandle, AnalogGyro, kNumAccumulators,
HAL_HandleEnum::AnalogGyro>
analogGyroHandles;
HAL_HandleEnum::AnalogGyro>* analogGyroHandles;
namespace hal {
namespace init {
void InitializeAnalogGyro() {
static IndexedHandleResource<HAL_GyroHandle, AnalogGyro, kNumAccumulators,
HAL_HandleEnum::AnalogGyro>
agHandles;
analogGyroHandles = &agHandles;
}
} // namespace init
} // namespace hal
static void Wait(double seconds) {
if (seconds < 0.0) return;
@@ -56,13 +66,13 @@ HAL_GyroHandle HAL_InitializeAnalogGyro(HAL_AnalogInputHandle analogHandle,
// handle known to be correct, so no need to type check
int16_t channel = getHandleIndex(analogHandle);
auto handle = analogGyroHandles.Allocate(channel, status);
auto handle = analogGyroHandles->Allocate(channel, status);
if (*status != 0)
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
// Initialize port structure
auto gyro = analogGyroHandles.Get(handle);
auto gyro = analogGyroHandles->Get(handle);
if (gyro == nullptr) { // would only error on thread issue
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
@@ -77,7 +87,7 @@ HAL_GyroHandle HAL_InitializeAnalogGyro(HAL_AnalogInputHandle analogHandle,
}
void HAL_SetupAnalogGyro(HAL_GyroHandle handle, int32_t* status) {
auto gyro = analogGyroHandles.Get(handle);
auto gyro = analogGyroHandles->Get(handle);
if (gyro == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -100,13 +110,13 @@ void HAL_SetupAnalogGyro(HAL_GyroHandle handle, int32_t* status) {
}
void HAL_FreeAnalogGyro(HAL_GyroHandle handle) {
analogGyroHandles.Free(handle);
analogGyroHandles->Free(handle);
}
void HAL_SetAnalogGyroParameters(HAL_GyroHandle handle,
double voltsPerDegreePerSecond, double offset,
int32_t center, int32_t* status) {
auto gyro = analogGyroHandles.Get(handle);
auto gyro = analogGyroHandles->Get(handle);
if (gyro == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -121,7 +131,7 @@ void HAL_SetAnalogGyroParameters(HAL_GyroHandle handle,
void HAL_SetAnalogGyroVoltsPerDegreePerSecond(HAL_GyroHandle handle,
double voltsPerDegreePerSecond,
int32_t* status) {
auto gyro = analogGyroHandles.Get(handle);
auto gyro = analogGyroHandles->Get(handle);
if (gyro == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -131,7 +141,7 @@ void HAL_SetAnalogGyroVoltsPerDegreePerSecond(HAL_GyroHandle handle,
}
void HAL_ResetAnalogGyro(HAL_GyroHandle handle, int32_t* status) {
auto gyro = analogGyroHandles.Get(handle);
auto gyro = analogGyroHandles->Get(handle);
if (gyro == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -149,7 +159,7 @@ void HAL_ResetAnalogGyro(HAL_GyroHandle handle, int32_t* status) {
}
void HAL_CalibrateAnalogGyro(HAL_GyroHandle handle, int32_t* status) {
auto gyro = analogGyroHandles.Get(handle);
auto gyro = analogGyroHandles->Get(handle);
if (gyro == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -176,7 +186,7 @@ void HAL_CalibrateAnalogGyro(HAL_GyroHandle handle, int32_t* status) {
void HAL_SetAnalogGyroDeadband(HAL_GyroHandle handle, double volts,
int32_t* status) {
auto gyro = analogGyroHandles.Get(handle);
auto gyro = analogGyroHandles->Get(handle);
if (gyro == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -189,7 +199,7 @@ void HAL_SetAnalogGyroDeadband(HAL_GyroHandle handle, double volts,
}
double HAL_GetAnalogGyroAngle(HAL_GyroHandle handle, int32_t* status) {
auto gyro = analogGyroHandles.Get(handle);
auto gyro = analogGyroHandles->Get(handle);
if (gyro == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -211,7 +221,7 @@ double HAL_GetAnalogGyroAngle(HAL_GyroHandle handle, int32_t* status) {
}
double HAL_GetAnalogGyroRate(HAL_GyroHandle handle, int32_t* status) {
auto gyro = analogGyroHandles.Get(handle);
auto gyro = analogGyroHandles->Get(handle);
if (gyro == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -225,7 +235,7 @@ double HAL_GetAnalogGyroRate(HAL_GyroHandle handle, int32_t* status) {
}
double HAL_GetAnalogGyroOffset(HAL_GyroHandle handle, int32_t* status) {
auto gyro = analogGyroHandles.Get(handle);
auto gyro = analogGyroHandles->Get(handle);
if (gyro == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -234,7 +244,7 @@ double HAL_GetAnalogGyroOffset(HAL_GyroHandle handle, int32_t* status) {
}
int32_t HAL_GetAnalogGyroCenter(HAL_GyroHandle handle, int32_t* status) {
auto gyro = analogGyroHandles.Get(handle);
auto gyro = analogGyroHandles->Get(handle);
if (gyro == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -7,9 +7,8 @@
#include "HAL/AnalogInput.h"
#include <mutex>
#include <FRC_NetworkCommunication/AICalibration.h>
#include <support/mutex.h>
#include "AnalogInternal.h"
#include "HAL/AnalogAccumulator.h"
@@ -17,6 +16,12 @@
#include "HAL/handles/HandlesInternal.h"
#include "PortsInternal.h"
namespace hal {
namespace init {
void InitializeAnalogInput() {}
} // namespace init
} // namespace hal
using namespace hal;
extern "C" {
@@ -38,13 +43,13 @@ HAL_AnalogInputHandle HAL_InitializeAnalogInputPort(HAL_PortHandle portHandle,
return HAL_kInvalidHandle;
}
HAL_AnalogInputHandle handle = analogInputHandles.Allocate(channel, status);
HAL_AnalogInputHandle handle = analogInputHandles->Allocate(channel, status);
if (*status != 0)
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
// Initialize port structure
auto analog_port = analogInputHandles.Get(handle);
auto analog_port = analogInputHandles->Get(handle);
if (analog_port == nullptr) { // would only error on thread issue
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
@@ -68,7 +73,7 @@ HAL_AnalogInputHandle HAL_InitializeAnalogInputPort(HAL_PortHandle portHandle,
*/
void HAL_FreeAnalogInputPort(HAL_AnalogInputHandle analogPortHandle) {
// no status, so no need to check for a proper free.
analogInputHandles.Free(analogPortHandle);
analogInputHandles->Free(analogPortHandle);
}
/**
@@ -136,7 +141,7 @@ double HAL_GetAnalogSampleRate(int32_t* status) {
*/
void HAL_SetAnalogAverageBits(HAL_AnalogInputHandle analogPortHandle,
int32_t bits, int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -156,7 +161,7 @@ void HAL_SetAnalogAverageBits(HAL_AnalogInputHandle analogPortHandle,
*/
int32_t HAL_GetAnalogAverageBits(HAL_AnalogInputHandle analogPortHandle,
int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return kDefaultAverageBits;
@@ -178,7 +183,7 @@ int32_t HAL_GetAnalogAverageBits(HAL_AnalogInputHandle analogPortHandle,
*/
void HAL_SetAnalogOversampleBits(HAL_AnalogInputHandle analogPortHandle,
int32_t bits, int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -199,7 +204,7 @@ void HAL_SetAnalogOversampleBits(HAL_AnalogInputHandle analogPortHandle,
*/
int32_t HAL_GetAnalogOversampleBits(HAL_AnalogInputHandle analogPortHandle,
int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return kDefaultOversampleBits;
@@ -220,7 +225,7 @@ int32_t HAL_GetAnalogOversampleBits(HAL_AnalogInputHandle analogPortHandle,
*/
int32_t HAL_GetAnalogValue(HAL_AnalogInputHandle analogPortHandle,
int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -230,7 +235,7 @@ int32_t HAL_GetAnalogValue(HAL_AnalogInputHandle analogPortHandle,
readSelect.Channel = port->channel;
readSelect.Averaged = false;
std::lock_guard<std::mutex> sync(analogRegisterWindowMutex);
std::lock_guard<wpi::mutex> lock(analogRegisterWindowMutex);
analogInputSystem->writeReadSelect(readSelect, status);
analogInputSystem->strobeLatchOutput(status);
return static_cast<int16_t>(analogInputSystem->readOutput(status));
@@ -252,7 +257,7 @@ int32_t HAL_GetAnalogValue(HAL_AnalogInputHandle analogPortHandle,
*/
int32_t HAL_GetAnalogAverageValue(HAL_AnalogInputHandle analogPortHandle,
int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -261,7 +266,7 @@ int32_t HAL_GetAnalogAverageValue(HAL_AnalogInputHandle analogPortHandle,
readSelect.Channel = port->channel;
readSelect.Averaged = true;
std::lock_guard<std::mutex> sync(analogRegisterWindowMutex);
std::lock_guard<wpi::mutex> lock(analogRegisterWindowMutex);
analogInputSystem->writeReadSelect(readSelect, status);
analogInputSystem->strobeLatchOutput(status);
return static_cast<int32_t>(analogInputSystem->readOutput(status));
@@ -352,7 +357,7 @@ int32_t HAL_GetAnalogVoltsToValue(HAL_AnalogInputHandle analogPortHandle,
*/
int32_t HAL_GetAnalogLSBWeight(HAL_AnalogInputHandle analogPortHandle,
int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -374,7 +379,7 @@ int32_t HAL_GetAnalogLSBWeight(HAL_AnalogInputHandle analogPortHandle,
*/
int32_t HAL_GetAnalogOffset(HAL_AnalogInputHandle analogPortHandle,
int32_t* status) {
auto port = analogInputHandles.Get(analogPortHandle);
auto port = analogInputHandles->Get(analogPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -8,7 +8,8 @@
#include "AnalogInternal.h"
#include <atomic>
#include <mutex>
#include <support/mutex.h>
#include "HAL/AnalogInput.h"
#include "HAL/ChipObject.h"
@@ -16,12 +17,12 @@
namespace hal {
std::mutex analogRegisterWindowMutex;
wpi::mutex analogRegisterWindowMutex;
std::unique_ptr<tAI> analogInputSystem;
std::unique_ptr<tAO> analogOutputSystem;
IndexedHandleResource<HAL_AnalogInputHandle, hal::AnalogPort, kNumAnalogInputs,
HAL_HandleEnum::AnalogInput>
IndexedHandleResource<HAL_AnalogInputHandle, ::hal::AnalogPort,
kNumAnalogInputs, HAL_HandleEnum::AnalogInput>*
analogInputHandles;
static int32_t analogNumChannelsToActivate = 0;
@@ -30,12 +31,21 @@ static std::atomic<bool> analogSystemInitialized{false};
bool analogSampleRateSet = false;
namespace init {
void InitializeAnalogInternal() {
static IndexedHandleResource<HAL_AnalogInputHandle, ::hal::AnalogPort,
kNumAnalogInputs, HAL_HandleEnum::AnalogInput>
alH;
analogInputHandles = &alH;
}
} // namespace init
/**
* Initialize the analog System.
*/
void initializeAnalog(int32_t* status) {
if (analogSystemInitialized) return;
std::lock_guard<std::mutex> sync(analogRegisterWindowMutex);
std::lock_guard<wpi::mutex> lock(analogRegisterWindowMutex);
if (analogSystemInitialized) return;
analogInputSystem.reset(tAI::create(status));
analogOutputSystem.reset(tAO::create(status));

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -10,7 +10,8 @@
#include <stdint.h>
#include <memory>
#include <mutex>
#include <support/mutex.h>
#include "HAL/ChipObject.h"
#include "HAL/Ports.h"
@@ -23,11 +24,11 @@ constexpr int32_t kTimebase = 40000000; ///< 40 MHz clock
constexpr int32_t kDefaultOversampleBits = 0;
constexpr int32_t kDefaultAverageBits = 7;
constexpr double kDefaultSampleRate = 50000.0;
static const uint32_t kAccumulatorChannels[] = {0, 1};
static constexpr uint32_t kAccumulatorChannels[] = {0, 1};
extern std::unique_ptr<tAI> analogInputSystem;
extern std::unique_ptr<tAO> analogOutputSystem;
extern std::mutex analogRegisterWindowMutex;
extern wpi::mutex analogRegisterWindowMutex;
extern bool analogSampleRateSet;
struct AnalogPort {
@@ -36,7 +37,7 @@ struct AnalogPort {
};
extern IndexedHandleResource<HAL_AnalogInputHandle, hal::AnalogPort,
kNumAnalogInputs, HAL_HandleEnum::AnalogInput>
kNumAnalogInputs, HAL_HandleEnum::AnalogInput>*
analogInputHandles;
int32_t getAnalogNumActiveChannels(int32_t* status);

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -24,9 +24,20 @@ struct AnalogOutput {
} // namespace
static IndexedHandleResource<HAL_AnalogOutputHandle, AnalogOutput,
kNumAnalogOutputs, HAL_HandleEnum::AnalogOutput>
kNumAnalogOutputs, HAL_HandleEnum::AnalogOutput>*
analogOutputHandles;
namespace hal {
namespace init {
void InitializeAnalogOutput() {
static IndexedHandleResource<HAL_AnalogOutputHandle, AnalogOutput,
kNumAnalogOutputs, HAL_HandleEnum::AnalogOutput>
aoH;
analogOutputHandles = &aoH;
}
} // namespace init
} // namespace hal
extern "C" {
/**
@@ -44,12 +55,13 @@ HAL_AnalogOutputHandle HAL_InitializeAnalogOutputPort(HAL_PortHandle portHandle,
return HAL_kInvalidHandle;
}
HAL_AnalogOutputHandle handle = analogOutputHandles.Allocate(channel, status);
HAL_AnalogOutputHandle handle =
analogOutputHandles->Allocate(channel, status);
if (*status != 0)
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
auto port = analogOutputHandles.Get(handle);
auto port = analogOutputHandles->Get(handle);
if (port == nullptr) { // would only error on thread issue
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
@@ -61,7 +73,7 @@ HAL_AnalogOutputHandle HAL_InitializeAnalogOutputPort(HAL_PortHandle portHandle,
void HAL_FreeAnalogOutputPort(HAL_AnalogOutputHandle analogOutputHandle) {
// no status, so no need to check for a proper free.
analogOutputHandles.Free(analogOutputHandle);
analogOutputHandles->Free(analogOutputHandle);
}
/**
@@ -77,7 +89,7 @@ HAL_Bool HAL_CheckAnalogOutputChannel(int32_t channel) {
void HAL_SetAnalogOutput(HAL_AnalogOutputHandle analogOutputHandle,
double voltage, int32_t* status) {
auto port = analogOutputHandles.Get(analogOutputHandle);
auto port = analogOutputHandles->Get(analogOutputHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -95,7 +107,7 @@ void HAL_SetAnalogOutput(HAL_AnalogOutputHandle analogOutputHandle,
double HAL_GetAnalogOutput(HAL_AnalogOutputHandle analogOutputHandle,
int32_t* status) {
auto port = analogOutputHandles.Get(analogOutputHandle);
auto port = analogOutputHandles->Get(analogOutputHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0.0;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -27,25 +27,37 @@ struct AnalogTrigger {
} // namespace
static LimitedHandleResource<HAL_AnalogTriggerHandle, AnalogTrigger,
kNumAnalogTriggers, HAL_HandleEnum::AnalogTrigger>
kNumAnalogTriggers, HAL_HandleEnum::AnalogTrigger>*
analogTriggerHandles;
namespace hal {
namespace init {
void InitializeAnalogTrigger() {
static LimitedHandleResource<HAL_AnalogTriggerHandle, AnalogTrigger,
kNumAnalogTriggers,
HAL_HandleEnum::AnalogTrigger>
atH;
analogTriggerHandles = &atH;
}
} // namespace init
} // namespace hal
extern "C" {
HAL_AnalogTriggerHandle HAL_InitializeAnalogTrigger(
HAL_AnalogInputHandle portHandle, int32_t* index, int32_t* status) {
// ensure we are given a valid and active AnalogInput handle
auto analog_port = analogInputHandles.Get(portHandle);
auto analog_port = analogInputHandles->Get(portHandle);
if (analog_port == nullptr) {
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
}
HAL_AnalogTriggerHandle handle = analogTriggerHandles.Allocate();
HAL_AnalogTriggerHandle handle = analogTriggerHandles->Allocate();
if (handle == HAL_kInvalidHandle) {
*status = NO_AVAILABLE_RESOURCES;
return HAL_kInvalidHandle;
}
auto trigger = analogTriggerHandles.Get(handle);
auto trigger = analogTriggerHandles->Get(handle);
if (trigger == nullptr) { // would only occur on thread issue
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
@@ -61,14 +73,14 @@ HAL_AnalogTriggerHandle HAL_InitializeAnalogTrigger(
void HAL_CleanAnalogTrigger(HAL_AnalogTriggerHandle analogTriggerHandle,
int32_t* status) {
analogTriggerHandles.Free(analogTriggerHandle);
analogTriggerHandles->Free(analogTriggerHandle);
// caller owns the analog input handle.
}
void HAL_SetAnalogTriggerLimitsRaw(HAL_AnalogTriggerHandle analogTriggerHandle,
int32_t lower, int32_t upper,
int32_t* status) {
auto trigger = analogTriggerHandles.Get(analogTriggerHandle);
auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
if (trigger == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -87,7 +99,7 @@ void HAL_SetAnalogTriggerLimitsRaw(HAL_AnalogTriggerHandle analogTriggerHandle,
void HAL_SetAnalogTriggerLimitsVoltage(
HAL_AnalogTriggerHandle analogTriggerHandle, double lower, double upper,
int32_t* status) {
auto trigger = analogTriggerHandles.Get(analogTriggerHandle);
auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
if (trigger == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -111,7 +123,7 @@ void HAL_SetAnalogTriggerLimitsVoltage(
*/
void HAL_SetAnalogTriggerAveraged(HAL_AnalogTriggerHandle analogTriggerHandle,
HAL_Bool useAveragedValue, int32_t* status) {
auto trigger = analogTriggerHandles.Get(analogTriggerHandle);
auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
if (trigger == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -132,7 +144,7 @@ void HAL_SetAnalogTriggerAveraged(HAL_AnalogTriggerHandle analogTriggerHandle,
*/
void HAL_SetAnalogTriggerFiltered(HAL_AnalogTriggerHandle analogTriggerHandle,
HAL_Bool useFilteredValue, int32_t* status) {
auto trigger = analogTriggerHandles.Get(analogTriggerHandle);
auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
if (trigger == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -152,7 +164,7 @@ void HAL_SetAnalogTriggerFiltered(HAL_AnalogTriggerHandle analogTriggerHandle,
*/
HAL_Bool HAL_GetAnalogTriggerInWindow(
HAL_AnalogTriggerHandle analogTriggerHandle, int32_t* status) {
auto trigger = analogTriggerHandles.Get(analogTriggerHandle);
auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
if (trigger == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
@@ -169,7 +181,7 @@ HAL_Bool HAL_GetAnalogTriggerInWindow(
*/
HAL_Bool HAL_GetAnalogTriggerTriggerState(
HAL_AnalogTriggerHandle analogTriggerHandle, int32_t* status) {
auto trigger = analogTriggerHandles.Get(analogTriggerHandle);
auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
if (trigger == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
@@ -184,7 +196,7 @@ HAL_Bool HAL_GetAnalogTriggerTriggerState(
HAL_Bool HAL_GetAnalogTriggerOutput(HAL_AnalogTriggerHandle analogTriggerHandle,
HAL_AnalogTriggerType type,
int32_t* status) {
auto trigger = analogTriggerHandles.Get(analogTriggerHandle);
auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
if (trigger == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -9,6 +9,12 @@
#include <FRC_NetworkCommunication/CANSessionMux.h>
namespace hal {
namespace init {
void InitializeCAN() {}
} // namespace init
} // namespace hal
extern "C" {
void HAL_CAN_SendMessage(uint32_t messageID, const uint8_t* data,

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -15,6 +15,12 @@
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) {

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,6 +11,12 @@
using namespace hal;
namespace hal {
namespace init {
void InitializeConstants() {}
} // namespace init
} // namespace hal
extern "C" {
int32_t HAL_GetSystemClockTicksPerMicrosecond(void) {

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -25,19 +25,29 @@ struct Counter {
} // namespace
static LimitedHandleResource<HAL_CounterHandle, Counter, kNumCounters,
HAL_HandleEnum::Counter>
counterHandles;
HAL_HandleEnum::Counter>* counterHandles;
namespace hal {
namespace init {
void InitializeCounter() {
static LimitedHandleResource<HAL_CounterHandle, Counter, kNumCounters,
HAL_HandleEnum::Counter>
ch;
counterHandles = &ch;
}
} // namespace init
} // namespace hal
extern "C" {
HAL_CounterHandle HAL_InitializeCounter(HAL_Counter_Mode mode, int32_t* index,
int32_t* status) {
auto handle = counterHandles.Allocate();
auto handle = counterHandles->Allocate();
if (handle == HAL_kInvalidHandle) { // out of resources
*status = NO_AVAILABLE_RESOURCES;
return HAL_kInvalidHandle;
}
auto counter = counterHandles.Get(handle);
auto counter = counterHandles->Get(handle);
if (counter == nullptr) { // would only occur on thread issues
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
@@ -52,12 +62,12 @@ HAL_CounterHandle HAL_InitializeCounter(HAL_Counter_Mode mode, int32_t* index,
}
void HAL_FreeCounter(HAL_CounterHandle counterHandle, int32_t* status) {
counterHandles.Free(counterHandle);
counterHandles->Free(counterHandle);
}
void HAL_SetCounterAverageSize(HAL_CounterHandle counterHandle, int32_t size,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -73,7 +83,7 @@ void HAL_SetCounterUpSource(HAL_CounterHandle counterHandle,
HAL_Handle digitalSourceHandle,
HAL_AnalogTriggerType analogTriggerType,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -110,7 +120,7 @@ void HAL_SetCounterUpSource(HAL_CounterHandle counterHandle,
void HAL_SetCounterUpSourceEdge(HAL_CounterHandle counterHandle,
HAL_Bool risingEdge, HAL_Bool fallingEdge,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -124,7 +134,7 @@ void HAL_SetCounterUpSourceEdge(HAL_CounterHandle counterHandle,
*/
void HAL_ClearCounterUpSource(HAL_CounterHandle counterHandle,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -144,7 +154,7 @@ void HAL_SetCounterDownSource(HAL_CounterHandle counterHandle,
HAL_Handle digitalSourceHandle,
HAL_AnalogTriggerType analogTriggerType,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -184,7 +194,7 @@ void HAL_SetCounterDownSource(HAL_CounterHandle counterHandle,
void HAL_SetCounterDownSourceEdge(HAL_CounterHandle counterHandle,
HAL_Bool risingEdge, HAL_Bool fallingEdge,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -198,7 +208,7 @@ void HAL_SetCounterDownSourceEdge(HAL_CounterHandle counterHandle,
*/
void HAL_ClearCounterDownSource(HAL_CounterHandle counterHandle,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -216,7 +226,7 @@ void HAL_ClearCounterDownSource(HAL_CounterHandle counterHandle,
*/
void HAL_SetCounterUpDownMode(HAL_CounterHandle counterHandle,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -231,7 +241,7 @@ void HAL_SetCounterUpDownMode(HAL_CounterHandle counterHandle,
*/
void HAL_SetCounterExternalDirectionMode(HAL_CounterHandle counterHandle,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -245,7 +255,7 @@ void HAL_SetCounterExternalDirectionMode(HAL_CounterHandle counterHandle,
*/
void HAL_SetCounterSemiPeriodMode(HAL_CounterHandle counterHandle,
HAL_Bool highSemiPeriod, int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -264,7 +274,7 @@ void HAL_SetCounterSemiPeriodMode(HAL_CounterHandle counterHandle,
*/
void HAL_SetCounterPulseLengthMode(HAL_CounterHandle counterHandle,
double threshold, int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -285,7 +295,7 @@ void HAL_SetCounterPulseLengthMode(HAL_CounterHandle counterHandle,
*/
int32_t HAL_GetCounterSamplesToAverage(HAL_CounterHandle counterHandle,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -301,7 +311,7 @@ int32_t HAL_GetCounterSamplesToAverage(HAL_CounterHandle counterHandle,
*/
void HAL_SetCounterSamplesToAverage(HAL_CounterHandle counterHandle,
int32_t samplesToAverage, int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -318,7 +328,7 @@ void HAL_SetCounterSamplesToAverage(HAL_CounterHandle counterHandle,
* counter, just sets the current value to zero.
*/
void HAL_ResetCounter(HAL_CounterHandle counterHandle, int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -332,7 +342,7 @@ void HAL_ResetCounter(HAL_CounterHandle counterHandle, int32_t* status) {
* current value. Next time it is read, it might have a different value.
*/
int32_t HAL_GetCounter(HAL_CounterHandle counterHandle, int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -348,7 +358,7 @@ int32_t HAL_GetCounter(HAL_CounterHandle counterHandle, int32_t* status) {
* @returns The period of the last two pulses in units of seconds.
*/
double HAL_GetCounterPeriod(HAL_CounterHandle counterHandle, int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0.0;
@@ -379,7 +389,7 @@ double HAL_GetCounterPeriod(HAL_CounterHandle counterHandle, int32_t* status) {
*/
void HAL_SetCounterMaxPeriod(HAL_CounterHandle counterHandle, double maxPeriod,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -403,7 +413,7 @@ void HAL_SetCounterMaxPeriod(HAL_CounterHandle counterHandle, double maxPeriod,
*/
void HAL_SetCounterUpdateWhenEmpty(HAL_CounterHandle counterHandle,
HAL_Bool enabled, int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -421,7 +431,7 @@ void HAL_SetCounterUpdateWhenEmpty(HAL_CounterHandle counterHandle,
*/
HAL_Bool HAL_GetCounterStopped(HAL_CounterHandle counterHandle,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
@@ -435,7 +445,7 @@ HAL_Bool HAL_GetCounterStopped(HAL_CounterHandle counterHandle,
*/
HAL_Bool HAL_GetCounterDirection(HAL_CounterHandle counterHandle,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
@@ -453,7 +463,7 @@ HAL_Bool HAL_GetCounterDirection(HAL_CounterHandle counterHandle,
void HAL_SetCounterReverseDirection(HAL_CounterHandle counterHandle,
HAL_Bool reverseDirection,
int32_t* status) {
auto counter = counterHandles.Get(counterHandle);
auto counter = counterHandles->Get(counterHandle);
if (counter == nullptr) {
*status = HAL_HANDLE_ERROR;
return;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -16,13 +16,25 @@
using namespace hal;
// Create a mutex to protect changes to the digital output values
static std::mutex digitalDIOMutex;
// Create a mutex to protect changes to the DO PWM config
static wpi::mutex digitalPwmMutex;
static LimitedHandleResource<HAL_DigitalPWMHandle, uint8_t,
kNumDigitalPWMOutputs, HAL_HandleEnum::DigitalPWM>
kNumDigitalPWMOutputs, HAL_HandleEnum::DigitalPWM>*
digitalPWMHandles;
namespace hal {
namespace init {
void InitializeDIO() {
static LimitedHandleResource<HAL_DigitalPWMHandle, uint8_t,
kNumDigitalPWMOutputs,
HAL_HandleEnum::DigitalPWM>
dpH;
digitalPWMHandles = &dpH;
}
} // namespace init
} // namespace hal
extern "C" {
/**
@@ -41,12 +53,12 @@ HAL_DigitalHandle HAL_InitializeDIOPort(HAL_PortHandle portHandle,
}
auto handle =
digitalChannelHandles.Allocate(channel, HAL_HandleEnum::DIO, status);
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);
auto port = digitalChannelHandles->Get(handle, HAL_HandleEnum::DIO);
if (port == nullptr) { // would only occur on thread issue.
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
@@ -54,7 +66,7 @@ HAL_DigitalHandle HAL_InitializeDIOPort(HAL_PortHandle portHandle,
port->channel = static_cast<uint8_t>(channel);
std::lock_guard<std::mutex> sync(digitalDIOMutex);
std::lock_guard<wpi::mutex> lock(digitalDIOMutex);
tDIO::tOutputEnable outputEnable = digitalSystem->readOutputEnable(status);
@@ -110,12 +122,12 @@ HAL_Bool HAL_CheckDIOChannel(int32_t channel) {
}
void HAL_FreeDIOPort(HAL_DigitalHandle dioPortHandle) {
auto port = digitalChannelHandles.Get(dioPortHandle, HAL_HandleEnum::DIO);
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
// no status, so no need to check for a proper free.
digitalChannelHandles.Free(dioPortHandle, HAL_HandleEnum::DIO);
digitalChannelHandles->Free(dioPortHandle, HAL_HandleEnum::DIO);
if (port == nullptr) return;
int32_t status = 0;
std::lock_guard<std::mutex> sync(digitalDIOMutex);
std::lock_guard<wpi::mutex> lock(digitalDIOMutex);
if (port->channel >= kNumDigitalHeaders + kNumDigitalMXPChannels) {
// Unset the SPI flag
int32_t bitToUnset = 1 << remapSPIChannel(port->channel);
@@ -139,13 +151,13 @@ void HAL_FreeDIOPort(HAL_DigitalHandle dioPortHandle) {
* @return PWM Generator handle
*/
HAL_DigitalPWMHandle HAL_AllocateDigitalPWM(int32_t* status) {
auto handle = digitalPWMHandles.Allocate();
auto handle = digitalPWMHandles->Allocate();
if (handle == HAL_kInvalidHandle) {
*status = NO_AVAILABLE_RESOURCES;
return HAL_kInvalidHandle;
}
auto id = digitalPWMHandles.Get(handle);
auto id = digitalPWMHandles->Get(handle);
if (id == nullptr) { // would only occur on thread issue.
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
@@ -162,7 +174,7 @@ HAL_DigitalPWMHandle HAL_AllocateDigitalPWM(int32_t* status) {
* allocateDigitalPWM()
*/
void HAL_FreeDigitalPWM(HAL_DigitalPWMHandle pwmGenerator, int32_t* status) {
digitalPWMHandles.Free(pwmGenerator);
digitalPWMHandles->Free(pwmGenerator);
}
/**
@@ -179,10 +191,8 @@ void HAL_SetDigitalPWMRate(double rate, int32_t* status) {
// TODO: Round in the linear rate domain.
initializeDigital(status);
if (*status != 0) return;
uint8_t pwmPeriodPower = static_cast<uint8_t>(
std::log(1.0 / (pwmSystem->readLoopTiming(status) * 0.25E-6 * rate)) /
std::log(2.0) +
0.5);
uint16_t pwmPeriodPower = static_cast<uint16_t>(
std::log(1.0 / (16 * 1.0E-6 * rate)) / std::log(2.0) + 0.5);
digitalSystem->writePWMPeriodPower(pwmPeriodPower, status);
}
@@ -194,7 +204,7 @@ void HAL_SetDigitalPWMRate(double rate, int32_t* status) {
*/
void HAL_SetDigitalPWMDutyCycle(HAL_DigitalPWMHandle pwmGenerator,
double dutyCycle, int32_t* status) {
auto port = digitalPWMHandles.Get(pwmGenerator);
auto port = digitalPWMHandles->Get(pwmGenerator);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -205,7 +215,7 @@ void HAL_SetDigitalPWMDutyCycle(HAL_DigitalPWMHandle pwmGenerator,
double rawDutyCycle = 256.0 * dutyCycle;
if (rawDutyCycle > 255.5) rawDutyCycle = 255.5;
{
std::lock_guard<std::mutex> sync(digitalPwmMutex);
std::lock_guard<wpi::mutex> lock(digitalPwmMutex);
uint16_t pwmPeriodPower = digitalSystem->readPWMPeriodPower(status);
if (pwmPeriodPower < 4) {
// The resolution of the duty cycle drops close to the highest
@@ -229,7 +239,7 @@ void HAL_SetDigitalPWMDutyCycle(HAL_DigitalPWMHandle pwmGenerator,
*/
void HAL_SetDigitalPWMOutputChannel(HAL_DigitalPWMHandle pwmGenerator,
int32_t channel, int32_t* status) {
auto port = digitalPWMHandles.Get(pwmGenerator);
auto port = digitalPWMHandles->Get(pwmGenerator);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -256,7 +266,7 @@ void HAL_SetDigitalPWMOutputChannel(HAL_DigitalPWMHandle pwmGenerator,
*/
void HAL_SetDIO(HAL_DigitalHandle dioPortHandle, HAL_Bool value,
int32_t* status) {
auto port = digitalChannelHandles.Get(dioPortHandle, HAL_HandleEnum::DIO);
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -265,7 +275,7 @@ void HAL_SetDIO(HAL_DigitalHandle dioPortHandle, HAL_Bool value,
if (value != 0) value = 1;
}
{
std::lock_guard<std::mutex> sync(digitalDIOMutex);
std::lock_guard<wpi::mutex> lock(digitalDIOMutex);
tDIO::tDO currentDIO = digitalSystem->readDO(status);
if (port->channel >= kNumDigitalHeaders + kNumDigitalMXPChannels) {
@@ -295,6 +305,50 @@ void HAL_SetDIO(HAL_DigitalHandle dioPortHandle, HAL_Bool value,
}
}
/**
* Set direction of a DIO channel.
*
* @param channel The Digital I/O channel
* @param input true to set input, false for output
*/
void HAL_SetDIODirection(HAL_DigitalHandle dioPortHandle, HAL_Bool input,
int32_t* status) {
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
{
std::lock_guard<wpi::mutex> lock(digitalDIOMutex);
tDIO::tOutputEnable currentDIO = digitalSystem->readOutputEnable(status);
if (port->channel >= kNumDigitalHeaders + kNumDigitalMXPChannels) {
if (input) {
currentDIO.SPIPort =
currentDIO.SPIPort & ~(1u << remapSPIChannel(port->channel));
} else {
currentDIO.SPIPort =
currentDIO.SPIPort | (1u << remapSPIChannel(port->channel));
}
} else if (port->channel < kNumDigitalHeaders) {
if (input) {
currentDIO.Headers = currentDIO.Headers & ~(1u << port->channel);
} else {
currentDIO.Headers = currentDIO.Headers | (1u << port->channel);
}
} else {
if (input) {
currentDIO.MXP =
currentDIO.MXP & ~(1u << remapMXPChannel(port->channel));
} else {
currentDIO.MXP =
currentDIO.MXP | (1u << remapMXPChannel(port->channel));
}
}
digitalSystem->writeOutputEnable(currentDIO, status);
}
}
/**
* Read a digital I/O bit from the FPGA.
* Get a single value from a digital I/O channel.
@@ -303,7 +357,7 @@ void HAL_SetDIO(HAL_DigitalHandle dioPortHandle, HAL_Bool value,
* @return The state of the specified channel
*/
HAL_Bool HAL_GetDIO(HAL_DigitalHandle dioPortHandle, int32_t* status) {
auto port = digitalChannelHandles.Get(dioPortHandle, HAL_HandleEnum::DIO);
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
@@ -331,7 +385,7 @@ HAL_Bool HAL_GetDIO(HAL_DigitalHandle dioPortHandle, int32_t* status) {
* @return The direction of the specified channel
*/
HAL_Bool HAL_GetDIODirection(HAL_DigitalHandle dioPortHandle, int32_t* status) {
auto port = digitalChannelHandles.Get(dioPortHandle, HAL_HandleEnum::DIO);
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
@@ -364,7 +418,7 @@ HAL_Bool HAL_GetDIODirection(HAL_DigitalHandle dioPortHandle, int32_t* status) {
*/
void HAL_Pulse(HAL_DigitalHandle dioPortHandle, double pulseLength,
int32_t* status) {
auto port = digitalChannelHandles.Get(dioPortHandle, HAL_HandleEnum::DIO);
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -392,7 +446,7 @@ void HAL_Pulse(HAL_DigitalHandle dioPortHandle, double pulseLength,
* @return A pulse is in progress
*/
HAL_Bool HAL_IsPulsing(HAL_DigitalHandle dioPortHandle, int32_t* status) {
auto port = digitalChannelHandles.Get(dioPortHandle, HAL_HandleEnum::DIO);
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
@@ -431,13 +485,13 @@ HAL_Bool HAL_IsAnyPulsing(int32_t* status) {
*/
void HAL_SetFilterSelect(HAL_DigitalHandle dioPortHandle, int32_t filterIndex,
int32_t* status) {
auto port = digitalChannelHandles.Get(dioPortHandle, HAL_HandleEnum::DIO);
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
std::lock_guard<std::mutex> sync(digitalDIOMutex);
std::lock_guard<wpi::mutex> lock(digitalDIOMutex);
if (port->channel >= kNumDigitalHeaders + kNumDigitalMXPChannels) {
// Channels 10-15 are SPI channels, so subtract our MXP channels
digitalSystem->writeFilterSelectHdr(port->channel - kNumDigitalMXPChannels,
@@ -459,13 +513,13 @@ void HAL_SetFilterSelect(HAL_DigitalHandle dioPortHandle, int32_t filterIndex,
* where 0 means "none" and 1 - 3 means filter # filterIndex - 1.
*/
int32_t HAL_GetFilterSelect(HAL_DigitalHandle dioPortHandle, int32_t* status) {
auto port = digitalChannelHandles.Get(dioPortHandle, HAL_HandleEnum::DIO);
auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
}
std::lock_guard<std::mutex> sync(digitalDIOMutex);
std::lock_guard<wpi::mutex> lock(digitalDIOMutex);
if (port->channel >= kNumDigitalHeaders + kNumDigitalMXPChannels) {
// Channels 10-15 are SPI channels, so subtract our MXP channels
return digitalSystem->readFilterSelectHdr(
@@ -492,7 +546,7 @@ int32_t HAL_GetFilterSelect(HAL_DigitalHandle dioPortHandle, int32_t* status) {
void HAL_SetFilterPeriod(int32_t filterIndex, int64_t value, int32_t* status) {
initializeDigital(status);
if (*status != 0) return;
std::lock_guard<std::mutex> sync(digitalDIOMutex);
std::lock_guard<wpi::mutex> lock(digitalDIOMutex);
digitalSystem->writeFilterPeriodHdr(filterIndex, value, status);
if (*status == 0) {
digitalSystem->writeFilterPeriodMXP(filterIndex, value, status);
@@ -517,7 +571,7 @@ int64_t HAL_GetFilterPeriod(int32_t filterIndex, int32_t* status) {
uint32_t hdrPeriod = 0;
uint32_t mxpPeriod = 0;
{
std::lock_guard<std::mutex> sync(digitalDIOMutex);
std::lock_guard<wpi::mutex> lock(digitalDIOMutex);
hdrPeriod = digitalSystem->readFilterPeriodHdr(filterIndex, status);
if (*status == 0) {
mxpPeriod = digitalSystem->readFilterPeriodMXP(filterIndex, status);

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -8,45 +8,76 @@
#include "DigitalInternal.h"
#include <atomic>
#include <mutex>
#include <thread>
#include <FRC_NetworkCommunication/LoadOut.h>
#include <support/mutex.h>
#include "ConstantsInternal.h"
#include "HAL/AnalogTrigger.h"
#include "HAL/ChipObject.h"
#include "HAL/HAL.h"
#include "HAL/Ports.h"
#include "HAL/cpp/UnsafeDIO.h"
#include "PortsInternal.h"
namespace hal {
// Create a mutex to protect changes to the DO PWM config
std::mutex digitalPwmMutex;
std::unique_ptr<tDIO> digitalSystem;
std::unique_ptr<tRelay> relaySystem;
std::unique_ptr<tPWM> pwmSystem;
std::unique_ptr<tSPI> spiSystem;
static std::atomic<bool> digitalSystemsInitialized{false};
static std::mutex initializeMutex;
// Create a mutex to protect changes to the digital output values
wpi::mutex digitalDIOMutex;
DigitalHandleResource<HAL_DigitalHandle, DigitalPort,
kNumDigitalChannels + kNumPWMHeaders>
kNumDigitalChannels + kNumPWMHeaders>*
digitalChannelHandles;
namespace init {
void InitializeDigitalInternal() {
static DigitalHandleResource<HAL_DigitalHandle, DigitalPort,
kNumDigitalChannels + kNumPWMHeaders>
dcH;
digitalChannelHandles = &dcH;
}
} // namespace init
namespace detail {
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) {
*status = HAL_HANDLE_ERROR;
return 0;
}
tDIO::tDO output;
output.value = 0;
if (port->channel >= kNumDigitalHeaders + kNumDigitalMXPChannels) {
output.SPIPort = (1u << remapSPIChannel(port->channel));
} else if (port->channel < kNumDigitalHeaders) {
output.Headers = (1u << port->channel);
} else {
output.MXP = (1u << remapMXPChannel(port->channel));
}
return output.value;
}
} // namespace detail
/**
* Initialize the digital system.
*/
void initializeDigital(int32_t* status) {
static std::atomic_bool initialized{false};
static wpi::mutex initializeMutex;
// Initial check, as if it's true initialization has finished
if (digitalSystemsInitialized) return;
if (initialized) return;
std::lock_guard<std::mutex> lock(initializeMutex);
std::lock_guard<wpi::mutex> lock(initializeMutex);
// Second check in case another thread was waiting
if (digitalSystemsInitialized) return;
if (initialized) return;
digitalSystem.reset(tDIO::create(status));
@@ -99,7 +130,7 @@ void initializeDigital(int32_t* status) {
// SPI setup
spiSystem.reset(tSPI::create(status));
digitalSystemsInitialized = true;
initialized = true;
}
/**
@@ -160,3 +191,8 @@ bool remapDigitalSource(HAL_Handle digitalSourceHandle,
}
} // namespace hal
// Unused function here to test template compile.
__attribute__((unused)) static void CompileFunctorTest() {
hal::UnsafeManipulateDIO(0, nullptr, [](hal::DIOSetProxy& proxy) {});
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -10,7 +10,8 @@
#include <stdint.h>
#include <memory>
#include <mutex>
#include <support/mutex.h>
#include "HAL/AnalogTrigger.h"
#include "HAL/ChipObject.h"
@@ -58,9 +59,6 @@ constexpr double kDefaultPwmCenter = 1.5;
constexpr int32_t kDefaultPwmStepsDown = 1000;
constexpr int32_t kPwmDisabled = 0;
// Create a mutex to protect changes to the DO PWM config
extern std::mutex digitalPwmMutex;
extern std::unique_ptr<tDIO> digitalSystem;
extern std::unique_ptr<tRelay> relaySystem;
extern std::unique_ptr<tPWM> pwmSystem;
@@ -78,9 +76,11 @@ struct DigitalPort {
};
extern DigitalHandleResource<HAL_DigitalHandle, DigitalPort,
kNumDigitalChannels + kNumPWMHeaders>
kNumDigitalChannels + kNumPWMHeaders>*
digitalChannelHandles;
extern wpi::mutex digitalDIOMutex;
void initializeDigital(int32_t* status);
bool remapDigitalSource(HAL_Handle digitalSourceHandle,
HAL_AnalogTriggerType analogTriggerType,

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -223,8 +223,19 @@ double Encoder::DecodingScaleFactor() const {
static LimitedClassedHandleResource<HAL_EncoderHandle, Encoder,
kNumEncoders + kNumCounters,
HAL_HandleEnum::Encoder>
encoderHandles;
HAL_HandleEnum::Encoder>* encoderHandles;
namespace hal {
namespace init {
void InitializeEncoder() {
static LimitedClassedHandleResource<HAL_EncoderHandle, Encoder,
kNumEncoders + kNumCounters,
HAL_HandleEnum::Encoder>
eH;
encoderHandles = &eH;
}
} // namespace init
} // namespace hal
extern "C" {
HAL_EncoderHandle HAL_InitializeEncoder(
@@ -236,7 +247,7 @@ HAL_EncoderHandle HAL_InitializeEncoder(
digitalSourceHandleA, analogTriggerTypeA, digitalSourceHandleB,
analogTriggerTypeB, reverseDirection, encodingType, status);
if (*status != 0) return HAL_kInvalidHandle; // return in creation error
auto handle = encoderHandles.Allocate(encoder);
auto handle = encoderHandles->Allocate(encoder);
if (handle == HAL_kInvalidHandle) {
*status = NO_AVAILABLE_RESOURCES;
return HAL_kInvalidHandle;
@@ -245,11 +256,11 @@ HAL_EncoderHandle HAL_InitializeEncoder(
}
void HAL_FreeEncoder(HAL_EncoderHandle encoderHandle, int32_t* status) {
encoderHandles.Free(encoderHandle);
encoderHandles->Free(encoderHandle);
}
int32_t HAL_GetEncoder(HAL_EncoderHandle encoderHandle, int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -258,7 +269,7 @@ int32_t HAL_GetEncoder(HAL_EncoderHandle encoderHandle, int32_t* status) {
}
int32_t HAL_GetEncoderRaw(HAL_EncoderHandle encoderHandle, int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -268,7 +279,7 @@ int32_t HAL_GetEncoderRaw(HAL_EncoderHandle encoderHandle, int32_t* status) {
int32_t HAL_GetEncoderEncodingScale(HAL_EncoderHandle encoderHandle,
int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -277,7 +288,7 @@ int32_t HAL_GetEncoderEncodingScale(HAL_EncoderHandle encoderHandle,
}
void HAL_ResetEncoder(HAL_EncoderHandle encoderHandle, int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -286,7 +297,7 @@ void HAL_ResetEncoder(HAL_EncoderHandle encoderHandle, int32_t* status) {
}
double HAL_GetEncoderPeriod(HAL_EncoderHandle encoderHandle, int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -296,7 +307,7 @@ double HAL_GetEncoderPeriod(HAL_EncoderHandle encoderHandle, int32_t* status) {
void HAL_SetEncoderMaxPeriod(HAL_EncoderHandle encoderHandle, double maxPeriod,
int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -306,7 +317,7 @@ void HAL_SetEncoderMaxPeriod(HAL_EncoderHandle encoderHandle, double maxPeriod,
HAL_Bool HAL_GetEncoderStopped(HAL_EncoderHandle encoderHandle,
int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -316,7 +327,7 @@ HAL_Bool HAL_GetEncoderStopped(HAL_EncoderHandle encoderHandle,
HAL_Bool HAL_GetEncoderDirection(HAL_EncoderHandle encoderHandle,
int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -326,7 +337,7 @@ HAL_Bool HAL_GetEncoderDirection(HAL_EncoderHandle encoderHandle,
double HAL_GetEncoderDistance(HAL_EncoderHandle encoderHandle,
int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -335,7 +346,7 @@ double HAL_GetEncoderDistance(HAL_EncoderHandle encoderHandle,
}
double HAL_GetEncoderRate(HAL_EncoderHandle encoderHandle, int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -345,7 +356,7 @@ double HAL_GetEncoderRate(HAL_EncoderHandle encoderHandle, int32_t* status) {
void HAL_SetEncoderMinRate(HAL_EncoderHandle encoderHandle, double minRate,
int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -355,7 +366,7 @@ void HAL_SetEncoderMinRate(HAL_EncoderHandle encoderHandle, double minRate,
void HAL_SetEncoderDistancePerPulse(HAL_EncoderHandle encoderHandle,
double distancePerPulse, int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -366,7 +377,7 @@ void HAL_SetEncoderDistancePerPulse(HAL_EncoderHandle encoderHandle,
void HAL_SetEncoderReverseDirection(HAL_EncoderHandle encoderHandle,
HAL_Bool reverseDirection,
int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -376,7 +387,7 @@ void HAL_SetEncoderReverseDirection(HAL_EncoderHandle encoderHandle,
void HAL_SetEncoderSamplesToAverage(HAL_EncoderHandle encoderHandle,
int32_t samplesToAverage, int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -386,7 +397,7 @@ void HAL_SetEncoderSamplesToAverage(HAL_EncoderHandle encoderHandle,
int32_t HAL_GetEncoderSamplesToAverage(HAL_EncoderHandle encoderHandle,
int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -396,7 +407,7 @@ int32_t HAL_GetEncoderSamplesToAverage(HAL_EncoderHandle encoderHandle,
double HAL_GetEncoderDecodingScaleFactor(HAL_EncoderHandle encoderHandle,
int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -406,7 +417,7 @@ double HAL_GetEncoderDecodingScaleFactor(HAL_EncoderHandle encoderHandle,
double HAL_GetEncoderDistancePerPulse(HAL_EncoderHandle encoderHandle,
int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -416,7 +427,7 @@ double HAL_GetEncoderDistancePerPulse(HAL_EncoderHandle encoderHandle,
HAL_EncoderEncodingType HAL_GetEncoderEncodingType(
HAL_EncoderHandle encoderHandle, int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return HAL_Encoder_k4X; // default to k4X
@@ -428,7 +439,7 @@ void HAL_SetEncoderIndexSource(HAL_EncoderHandle encoderHandle,
HAL_Handle digitalSourceHandle,
HAL_AnalogTriggerType analogTriggerType,
HAL_EncoderIndexingType type, int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -438,7 +449,7 @@ void HAL_SetEncoderIndexSource(HAL_EncoderHandle encoderHandle,
int32_t HAL_GetEncoderFPGAIndex(HAL_EncoderHandle encoderHandle,
int32_t* status) {
auto encoder = encoderHandles.Get(encoderHandle);
auto encoder = encoderHandles->Get(encoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -24,11 +24,21 @@ struct Encoder {
} // namespace
static const double DECODING_SCALING_FACTOR = 0.25;
static constexpr double DECODING_SCALING_FACTOR = 0.25;
static LimitedHandleResource<HAL_FPGAEncoderHandle, Encoder, kNumEncoders,
HAL_HandleEnum::FPGAEncoder>
fpgaEncoderHandles;
HAL_HandleEnum::FPGAEncoder>* fpgaEncoderHandles;
namespace hal {
namespace init {
void InitializeFPGAEncoder() {
static LimitedHandleResource<HAL_FPGAEncoderHandle, Encoder, kNumEncoders,
HAL_HandleEnum::FPGAEncoder>
feH;
fpgaEncoderHandles = &feH;
}
} // namespace init
} // namespace hal
extern "C" {
@@ -54,13 +64,13 @@ HAL_FPGAEncoderHandle HAL_InitializeFPGAEncoder(
return HAL_kInvalidHandle;
}
auto handle = fpgaEncoderHandles.Allocate();
auto handle = fpgaEncoderHandles->Allocate();
if (handle == HAL_kInvalidHandle) { // out of resources
*status = NO_AVAILABLE_RESOURCES;
return HAL_kInvalidHandle;
}
auto encoder = fpgaEncoderHandles.Get(handle);
auto encoder = fpgaEncoderHandles->Get(handle);
if (encoder == nullptr) { // will only error on thread issue
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
@@ -87,7 +97,7 @@ HAL_FPGAEncoderHandle HAL_InitializeFPGAEncoder(
void HAL_FreeFPGAEncoder(HAL_FPGAEncoderHandle fpgaEncoderHandle,
int32_t* status) {
fpgaEncoderHandles.Free(fpgaEncoderHandle);
fpgaEncoderHandles->Free(fpgaEncoderHandle);
}
/**
@@ -96,7 +106,7 @@ void HAL_FreeFPGAEncoder(HAL_FPGAEncoderHandle fpgaEncoderHandle,
*/
void HAL_ResetFPGAEncoder(HAL_FPGAEncoderHandle fpgaEncoderHandle,
int32_t* status) {
auto encoder = fpgaEncoderHandles.Get(fpgaEncoderHandle);
auto encoder = fpgaEncoderHandles->Get(fpgaEncoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -112,7 +122,7 @@ void HAL_ResetFPGAEncoder(HAL_FPGAEncoderHandle fpgaEncoderHandle,
*/
int32_t HAL_GetFPGAEncoder(HAL_FPGAEncoderHandle fpgaEncoderHandle,
int32_t* status) {
auto encoder = fpgaEncoderHandles.Get(fpgaEncoderHandle);
auto encoder = fpgaEncoderHandles->Get(fpgaEncoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -132,7 +142,7 @@ int32_t HAL_GetFPGAEncoder(HAL_FPGAEncoderHandle fpgaEncoderHandle,
*/
double HAL_GetFPGAEncoderPeriod(HAL_FPGAEncoderHandle fpgaEncoderHandle,
int32_t* status) {
auto encoder = fpgaEncoderHandles.Get(fpgaEncoderHandle);
auto encoder = fpgaEncoderHandles->Get(fpgaEncoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0.0;
@@ -169,7 +179,7 @@ double HAL_GetFPGAEncoderPeriod(HAL_FPGAEncoderHandle fpgaEncoderHandle,
*/
void HAL_SetFPGAEncoderMaxPeriod(HAL_FPGAEncoderHandle fpgaEncoderHandle,
double maxPeriod, int32_t* status) {
auto encoder = fpgaEncoderHandles.Get(fpgaEncoderHandle);
auto encoder = fpgaEncoderHandles->Get(fpgaEncoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -188,7 +198,7 @@ void HAL_SetFPGAEncoderMaxPeriod(HAL_FPGAEncoderHandle fpgaEncoderHandle,
*/
HAL_Bool HAL_GetFPGAEncoderStopped(HAL_FPGAEncoderHandle fpgaEncoderHandle,
int32_t* status) {
auto encoder = fpgaEncoderHandles.Get(fpgaEncoderHandle);
auto encoder = fpgaEncoderHandles->Get(fpgaEncoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
@@ -202,7 +212,7 @@ HAL_Bool HAL_GetFPGAEncoderStopped(HAL_FPGAEncoderHandle fpgaEncoderHandle,
*/
HAL_Bool HAL_GetFPGAEncoderDirection(HAL_FPGAEncoderHandle fpgaEncoderHandle,
int32_t* status) {
auto encoder = fpgaEncoderHandles.Get(fpgaEncoderHandle);
auto encoder = fpgaEncoderHandles->Get(fpgaEncoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
@@ -219,7 +229,7 @@ HAL_Bool HAL_GetFPGAEncoderDirection(HAL_FPGAEncoderHandle fpgaEncoderHandle,
void HAL_SetFPGAEncoderReverseDirection(HAL_FPGAEncoderHandle fpgaEncoderHandle,
HAL_Bool reverseDirection,
int32_t* status) {
auto encoder = fpgaEncoderHandles.Get(fpgaEncoderHandle);
auto encoder = fpgaEncoderHandles->Get(fpgaEncoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -236,7 +246,7 @@ void HAL_SetFPGAEncoderReverseDirection(HAL_FPGAEncoderHandle fpgaEncoderHandle,
void HAL_SetFPGAEncoderSamplesToAverage(HAL_FPGAEncoderHandle fpgaEncoderHandle,
int32_t samplesToAverage,
int32_t* status) {
auto encoder = fpgaEncoderHandles.Get(fpgaEncoderHandle);
auto encoder = fpgaEncoderHandles->Get(fpgaEncoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -255,7 +265,7 @@ void HAL_SetFPGAEncoderSamplesToAverage(HAL_FPGAEncoderHandle fpgaEncoderHandle,
*/
int32_t HAL_GetFPGAEncoderSamplesToAverage(
HAL_FPGAEncoderHandle fpgaEncoderHandle, int32_t* status) {
auto encoder = fpgaEncoderHandles.Get(fpgaEncoderHandle);
auto encoder = fpgaEncoderHandles->Get(fpgaEncoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -272,7 +282,7 @@ void HAL_SetFPGAEncoderIndexSource(HAL_FPGAEncoderHandle fpgaEncoderHandle,
HAL_AnalogTriggerType analogTriggerType,
HAL_Bool activeHigh, HAL_Bool edgeSensitive,
int32_t* status) {
auto encoder = fpgaEncoderHandles.Get(fpgaEncoderHandle);
auto encoder = fpgaEncoderHandles->Get(fpgaEncoderHandle);
if (encoder == nullptr) {
*status = HAL_HANDLE_ERROR;
return;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -7,14 +7,15 @@
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <mutex>
#include <FRC_NetworkCommunication/FRCComm.h>
#include <FRC_NetworkCommunication/NetCommRPCProxy_Occur.h>
#include <llvm/raw_ostream.h>
#include <support/condition_variable.h>
#include <support/mutex.h>
#include "HAL/DriverStation.h"
@@ -26,17 +27,21 @@ struct HAL_JoystickAxesInt {
int16_t axes[HAL_kMaxJoystickAxes];
};
static std::mutex msgMutex;
static std::condition_variable newDSDataAvailableCond;
static std::mutex newDSDataAvailableMutex;
static wpi::mutex msgMutex;
static wpi::condition_variable* newDSDataAvailableCond;
static wpi::mutex newDSDataAvailableMutex;
static int newDSDataAvailableCounter{0};
extern "C" {
int32_t HAL_SetErrorData(const char* errors, int32_t errorsLength,
int32_t waitMs) {
return setErrorData(errors, errorsLength, waitMs);
namespace hal {
namespace init {
void InitializeFRCDriverStation() {
static wpi::condition_variable nddaC;
newDSDataAvailableCond = &nddaC;
}
} // namespace init
} // namespace hal
extern "C" {
int32_t HAL_SendError(HAL_Bool isError, int32_t errorCode, HAL_Bool isLVCode,
const char* details, const char* location,
@@ -44,7 +49,7 @@ int32_t HAL_SendError(HAL_Bool isError, int32_t errorCode, HAL_Bool isLVCode,
// Avoid flooding console by keeping track of previous 5 error
// messages and only printing again if they're longer than 1 second old.
static constexpr int KEEP_MSGS = 5;
std::lock_guard<std::mutex> lock(msgMutex);
std::lock_guard<wpi::mutex> lock(msgMutex);
static std::string prevMsg[KEEP_MSGS];
static std::chrono::time_point<std::chrono::steady_clock>
prevMsgTime[KEEP_MSGS];
@@ -230,6 +235,67 @@ double HAL_GetMatchTime(int32_t* status) {
return matchTime;
}
int HAL_GetMatchInfo(HAL_MatchInfo* info) {
uint16_t gameSpecificMessageSize = 0;
int status = FRC_NetworkCommunication_getMatchInfo(
nullptr, nullptr, nullptr, nullptr, nullptr, &gameSpecificMessageSize);
if (status < 0) {
info->eventName = nullptr;
info->gameSpecificMessage = nullptr;
return status;
}
info->eventName = static_cast<char*>(std::malloc(256));
gameSpecificMessageSize = ((gameSpecificMessageSize + 1023) / 1024) * 1024;
uint16_t originalGameSpecificSize = gameSpecificMessageSize;
uint8_t* gameSpecificMessage =
static_cast<uint8_t*>(std::malloc(gameSpecificMessageSize));
MatchType_t matchType = MatchType_t::kMatchType_none;
uint16_t matchNumber = 0;
uint8_t replayNumber = 0;
status = FRC_NetworkCommunication_getMatchInfo(
info->eventName, &matchType, &matchNumber, &replayNumber,
gameSpecificMessage, &gameSpecificMessageSize);
if (status < 0) {
std::free(info->eventName);
std::free(gameSpecificMessage);
info->eventName = nullptr;
info->gameSpecificMessage = nullptr;
return status;
}
if (gameSpecificMessageSize >= originalGameSpecificSize) {
// Data has updated between size and read calls. Retry.
// Unless large lag, this call will be right.
std::free(gameSpecificMessage);
gameSpecificMessageSize = ((gameSpecificMessageSize + 1023) / 1024) * 1024;
gameSpecificMessage =
static_cast<uint8_t*>(std::malloc(gameSpecificMessageSize));
int status = FRC_NetworkCommunication_getMatchInfo(
nullptr, nullptr, nullptr, nullptr, gameSpecificMessage,
&gameSpecificMessageSize);
if (status < 0) {
std::free(info->eventName);
std::free(gameSpecificMessage);
info->eventName = nullptr;
info->gameSpecificMessage = nullptr;
return status;
}
}
info->eventName[255] = '\0';
info->matchType = static_cast<HAL_MatchType>(matchType);
info->matchNumber = matchNumber;
info->replayNumber = replayNumber;
info->gameSpecificMessage = reinterpret_cast<char*>(gameSpecificMessage);
info->gameSpecificMessage[gameSpecificMessageSize] = '\0';
return status;
}
void HAL_FreeMatchInfo(HAL_MatchInfo* info) {
std::free(info->eventName);
std::free(info->gameSpecificMessage);
info->eventName = nullptr;
info->gameSpecificMessage = nullptr;
}
void HAL_ObserveUserProgramStarting(void) {
FRC_NetworkCommunication_observeUserProgramStarting();
}
@@ -258,7 +324,7 @@ bool HAL_IsNewControlData(void) {
thread_local int lastCount{-1};
int currentCount = 0;
{
std::unique_lock<std::mutex> lock(newDSDataAvailableMutex);
std::unique_lock<wpi::mutex> lock(newDSDataAvailableMutex);
currentCount = newDSDataAvailableCounter;
}
if (lastCount == currentCount) return false;
@@ -280,37 +346,32 @@ HAL_Bool HAL_WaitForDSDataTimeout(double timeout) {
auto timeoutTime =
std::chrono::steady_clock::now() + std::chrono::duration<double>(timeout);
std::unique_lock<std::mutex> lock(newDSDataAvailableMutex);
std::unique_lock<wpi::mutex> lock(newDSDataAvailableMutex);
int currentCount = newDSDataAvailableCounter;
while (newDSDataAvailableCounter == currentCount) {
if (timeout > 0) {
auto timedOut = newDSDataAvailableCond.wait_until(lock, timeoutTime);
auto timedOut = newDSDataAvailableCond->wait_until(lock, timeoutTime);
if (timedOut == std::cv_status::timeout) {
return false;
}
} else {
newDSDataAvailableCond.wait(lock);
newDSDataAvailableCond->wait(lock);
}
}
return true;
}
// Internal NetComm function to set new packet callback
extern int NetCommRPCProxy_SetOccurFuncPointer(
int32_t (*occurFunc)(uint32_t refNum));
// Constant number to be used for our occur handle
constexpr int32_t refNumber = 42;
static int32_t newDataOccur(uint32_t refNum) {
static void newDataOccur(uint32_t refNum) {
// Since we could get other values, require our specific handle
// to signal our threads
if (refNum != refNumber) return 0;
std::lock_guard<std::mutex> lock(newDSDataAvailableMutex);
if (refNum != refNumber) return;
std::lock_guard<wpi::mutex> lock(newDSDataAvailableMutex);
// Nofify all threads
newDSDataAvailableCounter++;
newDSDataAvailableCond.notify_all();
return 0;
newDSDataAvailableCond->notify_all();
}
/*
@@ -320,11 +381,11 @@ static int32_t newDataOccur(uint32_t refNum) {
*/
void HAL_InitializeDriverStation(void) {
static std::atomic_bool initialized{false};
static std::mutex initializeMutex;
static wpi::mutex initializeMutex;
// Initial check, as if it's true initialization has finished
if (initialized) return;
std::lock_guard<std::mutex> lock(initializeMutex);
std::lock_guard<wpi::mutex> lock(initializeMutex);
// Second check in case another thread was waiting
if (initialized) return;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -14,19 +14,20 @@
#include <atomic>
#include <cstdlib>
#include <fstream>
#include <mutex>
#include <thread>
#include <FRC_NetworkCommunication/FRCComm.h>
#include <FRC_NetworkCommunication/LoadOut.h>
#include <llvm/raw_ostream.h>
#include <support/mutex.h>
#include <support/timestamp.h>
#include "HAL/ChipObject.h"
#include "HAL/DriverStation.h"
#include "HAL/Errors.h"
#include "HAL/Notifier.h"
#include "HAL/cpp/NotifierInternal.h"
#include "HAL/handles/HandlesInternal.h"
#include "HALInitializer.h"
#include "ctre/ctre.h"
#include "visa/visa.h"
@@ -37,6 +38,44 @@ static std::unique_ptr<tSysWatchdog> watchdog;
using namespace hal;
namespace hal {
namespace init {
void InitializeHAL() {
InitializeHandlesInternal();
InitializeAccelerometer();
InitializeAnalogAccumulator();
InitializeAnalogGyro();
InitializeAnalogInput();
InitializeAnalogInternal();
InitializeAnalogOutput();
InitializeAnalogTrigger();
InitializeCAN();
InitializeCompressor();
InitializeConstants();
InitializeCounter();
InitializeDigitalInternal();
InitializeDIO();
InitializeEncoder();
InitializeFPGAEncoder();
InitializeFRCDriverStation();
InitializeI2C();
InitialzeInterrupts();
InitializeNotifier();
InitializeOSSerialPort();
InitializePCMInternal();
InitializePDP();
InitializePorts();
InitializePower();
InitializePWM();
InitializeRelay();
InitializeSerialPort();
InitializeSolenoid();
InitializeSPI();
InitializeThreads();
}
} // namespace init
} // namespace hal
extern "C" {
HAL_PortHandle HAL_GetPort(int32_t channel) {
@@ -177,7 +216,7 @@ const char* HAL_GetErrorMessage(int32_t code) {
/**
* Returns the runtime type of this HAL
*/
HAL_RuntimeType HAL_GetRuntimeType() { return HAL_Athena; }
HAL_RuntimeType HAL_GetRuntimeType(void) { return HAL_Athena; }
/**
* Return the FPGA Version number.
@@ -219,6 +258,7 @@ uint64_t HAL_GetFPGATime(int32_t* status) {
*status = NiFpga_Status_ResourceNotInitialized;
return 0;
}
uint64_t upper1 = global->readLocalTimeUpper(status);
uint32_t lower = global->readLocalTime(status);
uint64_t upper2 = global->readLocalTimeUpper(status);
@@ -261,11 +301,11 @@ HAL_Bool HAL_GetBrownedOut(int32_t* status) {
void HAL_BaseInitialize(int32_t* status) {
static std::atomic_bool initialized{false};
static std::mutex initializeMutex;
static wpi::mutex initializeMutex;
// Initial check, as if it's true initialization has finished
if (initialized) return;
std::lock_guard<std::mutex> lock(initializeMutex);
std::lock_guard<wpi::mutex> lock(initializeMutex);
// Second check in case another thread was waiting
if (initialized) return;
// image 4; Fixes errors caused by multiple processes. Talk to NI about this
@@ -323,14 +363,16 @@ static bool killExistingProgram(int timeout, int mode) {
*/
HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) {
static std::atomic_bool initialized{false};
static std::mutex initializeMutex;
static wpi::mutex initializeMutex;
// Initial check, as if it's true initialization has finished
if (initialized) return true;
std::lock_guard<std::mutex> lock(initializeMutex);
std::lock_guard<wpi::mutex> lock(initializeMutex);
// Second check in case another thread was waiting
if (initialized) return true;
hal::init::InitializeHAL();
setlinebuf(stdin);
setlinebuf(stdout);
llvm::outs().SetUnbuffered();
@@ -351,9 +393,24 @@ HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) {
int32_t status = 0;
HAL_BaseInitialize(&status);
if (status != 0) return false;
HAL_InitializeDriverStation();
// Set WPI_Now to use FPGA timestamp
wpi::SetNowImpl([]() -> uint64_t {
int32_t status = 0;
uint64_t rv = HAL_GetFPGATime(&status);
if (status != 0) {
llvm::errs()
<< "Call to HAL_GetFPGATime failed."
<< "Initialization might have failed. Time will not be correct\n";
llvm::errs().flush();
return 0u;
}
return rv;
});
initialized = true;
return true;
}
@@ -370,8 +427,8 @@ int64_t HAL_Report(int32_t resource, int32_t instanceNumber, int32_t context,
// TODO: HACKS
// No need for header definitions, as we should not run from user code.
void NumericArrayResize() {}
void RTSetCleanupProc() {}
void EDVR_CreateReference() {}
void NumericArrayResize(void) {}
void RTSetCleanupProc(void) {}
void EDVR_CreateReference(void) {}
} // extern "C"

View File

@@ -0,0 +1,45 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
namespace hal {
namespace init {
extern void InitializeAccelerometer();
extern void InitializeAnalogAccumulator();
extern void InitializeAnalogGyro();
extern void InitializeAnalogInput();
extern void InitializeAnalogInternal();
extern void InitializeAnalogOutput();
extern void InitializeAnalogTrigger();
extern void InitializeCAN();
extern void InitializeCompressor();
extern void InitializeConstants();
extern void InitializeCounter();
extern void InitializeDigitalInternal();
extern void InitializeDIO();
extern void InitializeEncoder();
extern void InitializeFPGAEncoder();
extern void InitializeFRCDriverStation();
extern void InitializeHAL();
extern void InitializeI2C();
extern void InitialzeInterrupts();
extern void InitializeNotifier();
extern void InitializeOSSerialPort();
extern void InitializePCMInternal();
extern void InitializePDP();
extern void InitializePorts();
extern void InitializePower();
extern void InitializePWM();
extern void InitializeRelay();
extern void InitializeSerialPort();
extern void InitializeSolenoid();
extern void InitializeSPI();
extern void InitializeThreads();
extern void InitializeHandlesInternal();
} // namespace init
} // namespace hal

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -7,7 +7,13 @@
#include "HAL/I2C.h"
#include <i2clib/i2c-lib.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <cstring>
#include "DigitalInternal.h"
#include "HAL/DIO.h"
@@ -15,16 +21,22 @@
using namespace hal;
static std::mutex digitalI2COnBoardMutex;
static std::mutex digitalI2CMXPMutex;
static wpi::mutex digitalI2COnBoardMutex;
static wpi::mutex digitalI2CMXPMutex;
static uint8_t i2COnboardObjCount = 0;
static uint8_t i2CMXPObjCount = 0;
static uint8_t i2COnBoardHandle = 0;
static uint8_t i2CMXPHandle = 0;
static uint8_t i2COnboardObjCount{0};
static uint8_t i2CMXPObjCount{0};
static int i2COnBoardHandle{-1};
static int i2CMXPHandle{-1};
static HAL_DigitalHandle i2CMXPDigitalHandle1 = HAL_kInvalidHandle;
static HAL_DigitalHandle i2CMXPDigitalHandle2 = HAL_kInvalidHandle;
static HAL_DigitalHandle i2CMXPDigitalHandle1{HAL_kInvalidHandle};
static HAL_DigitalHandle i2CMXPDigitalHandle2{HAL_kInvalidHandle};
namespace hal {
namespace init {
void InitializeI2C() {}
} // namespace init
} // namespace hal
extern "C" {
@@ -42,30 +54,37 @@ void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) {
return;
}
std::mutex& lock = port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
{
std::lock_guard<std::mutex> sync(lock);
if (port == 0) {
i2COnboardObjCount++;
if (i2COnBoardHandle > 0) return;
i2COnBoardHandle = i2clib_open("/dev/i2c-2");
} else if (port == 1) {
i2CMXPObjCount++;
if (i2CMXPHandle > 0) return;
if ((i2CMXPDigitalHandle1 = HAL_InitializeDIOPort(
HAL_GetPort(24), false, status)) == HAL_kInvalidHandle) {
return;
}
if ((i2CMXPDigitalHandle2 = HAL_InitializeDIOPort(
HAL_GetPort(25), false, status)) == HAL_kInvalidHandle) {
HAL_FreeDIOPort(i2CMXPDigitalHandle1); // free the first port allocated
return;
}
digitalSystem->writeEnableMXPSpecialFunction(
digitalSystem->readEnableMXPSpecialFunction(status) | 0xC000, status);
i2CMXPHandle = i2clib_open("/dev/i2c-1");
if (port == 0) {
std::lock_guard<wpi::mutex> lock(digitalI2COnBoardMutex);
i2COnboardObjCount++;
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));
return;
}
return;
i2COnBoardHandle = handle;
} else {
std::lock_guard<wpi::mutex> lock(digitalI2CMXPMutex);
i2CMXPObjCount++;
if (i2CMXPObjCount > 1) return;
if ((i2CMXPDigitalHandle1 = HAL_InitializeDIOPort(
HAL_GetPort(24), false, status)) == HAL_kInvalidHandle) {
return;
}
if ((i2CMXPDigitalHandle2 = HAL_InitializeDIOPort(
HAL_GetPort(25), false, status)) == HAL_kInvalidHandle) {
HAL_FreeDIOPort(i2CMXPDigitalHandle1); // free the first port allocated
return;
}
digitalSystem->writeEnableMXPSpecialFunction(
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));
return;
}
i2CMXPHandle = handle;
}
}
@@ -82,22 +101,33 @@ void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) {
* @return >= 0 on success or -1 on transfer abort.
*/
int32_t HAL_TransactionI2C(HAL_I2CPort port, int32_t deviceAddress,
uint8_t* dataToSend, int32_t sendSize,
const uint8_t* dataToSend, int32_t sendSize,
uint8_t* dataReceived, int32_t receiveSize) {
if (port > 1) {
// Set port out of range error here
return -1;
}
int32_t handle = port == 0 ? i2COnBoardHandle : i2CMXPHandle;
std::mutex& lock = port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
struct i2c_msg msgs[2];
msgs[0].addr = deviceAddress;
msgs[0].flags = 0;
msgs[0].len = sendSize;
msgs[0].buf = const_cast<uint8_t*>(dataToSend);
msgs[1].addr = deviceAddress;
msgs[1].flags = I2C_M_RD;
msgs[1].len = receiveSize;
msgs[1].buf = dataReceived;
{
std::lock_guard<std::mutex> sync(lock);
return i2clib_writeread(
handle, deviceAddress, reinterpret_cast<const char*>(dataToSend),
static_cast<int32_t>(sendSize), reinterpret_cast<char*>(dataReceived),
static_cast<int32_t>(receiveSize));
struct i2c_rdwr_ioctl_data rdwr;
rdwr.msgs = msgs;
rdwr.nmsgs = 2;
if (port == 0) {
std::lock_guard<wpi::mutex> lock(digitalI2COnBoardMutex);
return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr);
} else {
std::lock_guard<wpi::mutex> lock(digitalI2CMXPMutex);
return ioctl(i2CMXPHandle, I2C_RDWR, &rdwr);
}
}
@@ -113,18 +143,28 @@ int32_t HAL_TransactionI2C(HAL_I2CPort port, int32_t deviceAddress,
* @return >= 0 on success or -1 on transfer abort.
*/
int32_t HAL_WriteI2C(HAL_I2CPort port, int32_t deviceAddress,
uint8_t* dataToSend, int32_t sendSize) {
const uint8_t* dataToSend, int32_t sendSize) {
if (port > 1) {
// Set port out of range error here
return -1;
}
int32_t handle = port == 0 ? i2COnBoardHandle : i2CMXPHandle;
std::mutex& lock = port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
{
std::lock_guard<std::mutex> sync(lock);
return i2clib_write(handle, deviceAddress,
reinterpret_cast<const char*>(dataToSend), sendSize);
struct i2c_msg msg;
msg.addr = deviceAddress;
msg.flags = 0;
msg.len = sendSize;
msg.buf = const_cast<uint8_t*>(dataToSend);
struct i2c_rdwr_ioctl_data rdwr;
rdwr.msgs = &msg;
rdwr.nmsgs = 1;
if (port == 0) {
std::lock_guard<wpi::mutex> lock(digitalI2COnBoardMutex);
return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr);
} else {
std::lock_guard<wpi::mutex> lock(digitalI2CMXPMutex);
return ioctl(i2CMXPHandle, I2C_RDWR, &rdwr);
}
}
@@ -148,12 +188,22 @@ int32_t HAL_ReadI2C(HAL_I2CPort port, int32_t deviceAddress, uint8_t* buffer,
return -1;
}
int32_t handle = port == 0 ? i2COnBoardHandle : i2CMXPHandle;
std::mutex& lock = port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
{
std::lock_guard<std::mutex> sync(lock);
return i2clib_read(handle, deviceAddress, reinterpret_cast<char*>(buffer),
static_cast<int32_t>(count));
struct i2c_msg msg;
msg.addr = deviceAddress;
msg.flags = I2C_M_RD;
msg.len = count;
msg.buf = buffer;
struct i2c_rdwr_ioctl_data rdwr;
rdwr.msgs = &msg;
rdwr.nmsgs = 1;
if (port == 0) {
std::lock_guard<wpi::mutex> lock(digitalI2COnBoardMutex);
return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr);
} else {
std::lock_guard<wpi::mutex> lock(digitalI2CMXPMutex);
return ioctl(i2CMXPHandle, I2C_RDWR, &rdwr);
}
}
@@ -162,20 +212,20 @@ void HAL_CloseI2C(HAL_I2CPort port) {
// Set port out of range error here
return;
}
std::mutex& lock = port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
{
std::lock_guard<std::mutex> sync(lock);
if ((port == 0 ? i2COnboardObjCount-- : i2CMXPObjCount--) == 0) {
int32_t handle = port == 0 ? i2COnBoardHandle : i2CMXPHandle;
i2clib_close(handle);
}
}
if (port == 1) {
if (port == 0) {
std::lock_guard<wpi::mutex> lock(digitalI2COnBoardMutex);
if (i2COnboardObjCount-- == 0) {
close(i2COnBoardHandle);
}
} else {
std::lock_guard<wpi::mutex> lock(digitalI2CMXPMutex);
if (i2CMXPObjCount-- == 0) {
close(i2CMXPHandle);
}
HAL_FreeDIOPort(i2CMXPDigitalHandle1);
HAL_FreeDIOPort(i2CMXPDigitalHandle2);
}
return;
}
} // extern "C"

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -32,7 +32,7 @@ struct Interrupt {
class InterruptThread : public wpi::SafeThread {
public:
void Main() {
std::unique_lock<std::mutex> lock(m_mutex);
std::unique_lock<wpi::mutex> lock(m_mutex);
while (m_active) {
m_cond.wait(lock, [&] { return !m_active || m_notify; });
if (!m_active) break;
@@ -77,19 +77,29 @@ static void threadedInterruptHandler(uint32_t mask, void* param) {
}
static LimitedHandleResource<HAL_InterruptHandle, Interrupt, kNumInterrupts,
HAL_HandleEnum::Interrupt>
interruptHandles;
HAL_HandleEnum::Interrupt>* interruptHandles;
namespace hal {
namespace init {
void InitialzeInterrupts() {
static LimitedHandleResource<HAL_InterruptHandle, Interrupt, kNumInterrupts,
HAL_HandleEnum::Interrupt>
iH;
interruptHandles = &iH;
}
} // namespace init
} // namespace hal
extern "C" {
HAL_InterruptHandle HAL_InitializeInterrupts(HAL_Bool watcher,
int32_t* status) {
HAL_InterruptHandle handle = interruptHandles.Allocate();
HAL_InterruptHandle handle = interruptHandles->Allocate();
if (handle == HAL_kInvalidHandle) {
*status = NO_AVAILABLE_RESOURCES;
return HAL_kInvalidHandle;
}
auto anInterrupt = interruptHandles.Get(handle);
auto anInterrupt = interruptHandles->Get(handle);
uint32_t interruptIndex = static_cast<uint32_t>(getHandleIndex(handle));
// Expects the calling leaf class to allocate an interrupt index.
anInterrupt->anInterrupt.reset(tInterrupt::create(interruptIndex, status));
@@ -100,7 +110,7 @@ HAL_InterruptHandle HAL_InitializeInterrupts(HAL_Bool watcher,
}
void HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle, int32_t* status) {
interruptHandles.Free(interruptHandle);
interruptHandles->Free(interruptHandle);
}
/**
@@ -114,7 +124,7 @@ int64_t HAL_WaitForInterrupt(HAL_InterruptHandle interruptHandle,
double timeout, HAL_Bool ignorePrevious,
int32_t* status) {
uint32_t result;
auto anInterrupt = interruptHandles.Get(interruptHandle);
auto anInterrupt = interruptHandles->Get(interruptHandle);
if (anInterrupt == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -140,7 +150,7 @@ int64_t HAL_WaitForInterrupt(HAL_InterruptHandle interruptHandle,
*/
void HAL_EnableInterrupts(HAL_InterruptHandle interruptHandle,
int32_t* status) {
auto anInterrupt = interruptHandles.Get(interruptHandle);
auto anInterrupt = interruptHandles->Get(interruptHandle);
if (anInterrupt == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -153,7 +163,7 @@ void HAL_EnableInterrupts(HAL_InterruptHandle interruptHandle,
*/
void HAL_DisableInterrupts(HAL_InterruptHandle interruptHandle,
int32_t* status) {
auto anInterrupt = interruptHandles.Get(interruptHandle);
auto anInterrupt = interruptHandles->Get(interruptHandle);
if (anInterrupt == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -168,7 +178,7 @@ void HAL_DisableInterrupts(HAL_InterruptHandle interruptHandle,
*/
double HAL_ReadInterruptRisingTimestamp(HAL_InterruptHandle interruptHandle,
int32_t* status) {
auto anInterrupt = interruptHandles.Get(interruptHandle);
auto anInterrupt = interruptHandles->Get(interruptHandle);
if (anInterrupt == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -178,13 +188,13 @@ double HAL_ReadInterruptRisingTimestamp(HAL_InterruptHandle interruptHandle,
}
/**
* Return the timestamp for the falling interrupt that occurred most recently.
* This is in the same time domain as GetClock().
* @return Timestamp in seconds since boot.
*/
* Return the timestamp for the falling interrupt that occurred most recently.
* This is in the same time domain as GetClock().
* @return Timestamp in seconds since boot.
*/
double HAL_ReadInterruptFallingTimestamp(HAL_InterruptHandle interruptHandle,
int32_t* status) {
auto anInterrupt = interruptHandles.Get(interruptHandle);
auto anInterrupt = interruptHandles->Get(interruptHandle);
if (anInterrupt == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -197,7 +207,7 @@ void HAL_RequestInterrupts(HAL_InterruptHandle interruptHandle,
HAL_Handle digitalSourceHandle,
HAL_AnalogTriggerType analogTriggerType,
int32_t* status) {
auto anInterrupt = interruptHandles.Get(interruptHandle);
auto anInterrupt = interruptHandles->Get(interruptHandle);
if (anInterrupt == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -222,7 +232,7 @@ void HAL_RequestInterrupts(HAL_InterruptHandle interruptHandle,
void HAL_AttachInterruptHandler(HAL_InterruptHandle interruptHandle,
HAL_InterruptHandlerFunction handler,
void* param, int32_t* status) {
auto anInterrupt = interruptHandles.Get(interruptHandle);
auto anInterrupt = interruptHandles->Get(interruptHandle);
if (anInterrupt == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -248,7 +258,7 @@ void HAL_AttachInterruptHandlerThreaded(HAL_InterruptHandle interrupt_handle,
void HAL_SetInterruptUpSourceEdge(HAL_InterruptHandle interruptHandle,
HAL_Bool risingEdge, HAL_Bool fallingEdge,
int32_t* status) {
auto anInterrupt = interruptHandles.Get(interruptHandle);
auto anInterrupt = interruptHandles->Get(interruptHandle);
if (anInterrupt == nullptr) {
*status = HAL_HANDLE_ERROR;
return;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -10,124 +10,63 @@
#include <atomic>
#include <cstdlib> // For std::atexit()
#include <memory>
#include <mutex>
#include <support/SafeThread.h>
#include <support/condition_variable.h>
#include <support/mutex.h>
#include "HAL/ChipObject.h"
#include "HAL/Errors.h"
#include "HAL/HAL.h"
#include "HAL/cpp/NotifierInternal.h"
#include "HAL/cpp/make_unique.h"
#include "HAL/handles/UnlimitedHandleResource.h"
using namespace hal;
static const int32_t kTimerInterruptNumber = 28;
static constexpr int32_t kTimerInterruptNumber = 28;
static std::mutex notifierInterruptMutex;
static std::mutex notifierMutex;
static wpi::mutex notifierMutex;
static std::unique_ptr<tAlarm> notifierAlarm;
static std::unique_ptr<tInterruptManager> notifierManager;
static uint64_t closestTrigger = UINT64_MAX;
static uint64_t closestTrigger{UINT64_MAX};
namespace {
struct Notifier {
std::shared_ptr<Notifier> prev, next;
void* param;
HAL_NotifierProcessFunction process;
uint64_t triggerTime = UINT64_MAX;
HAL_NotifierHandle handle;
bool threaded;
};
// Safe thread to allow callbacks to run on their own thread
class NotifierThread : public wpi::SafeThread {
public:
void Main() {
std::unique_lock<std::mutex> lock(m_mutex);
while (m_active) {
m_cond.wait(lock, [&] { return !m_active || m_notify; });
if (!m_active) break;
m_notify = false;
uint64_t currentTime = m_currentTime;
HAL_NotifierHandle handle = m_handle;
HAL_NotifierProcessFunction process = m_process;
lock.unlock(); // don't hold mutex during callback execution
process(currentTime, handle);
lock.lock();
}
}
bool m_notify = false;
HAL_NotifierHandle m_handle = HAL_kInvalidHandle;
HAL_NotifierProcessFunction m_process;
uint64_t m_currentTime;
};
class NotifierThreadOwner : public wpi::SafeThreadOwner<NotifierThread> {
public:
void SetFunc(HAL_NotifierProcessFunction process, void* param) {
auto thr = GetThread();
if (!thr) return;
thr->m_process = process;
m_param = param;
}
void Notify(uint64_t currentTime, HAL_NotifierHandle handle) {
auto thr = GetThread();
if (!thr) return;
thr->m_currentTime = currentTime;
thr->m_handle = handle;
thr->m_notify = true;
thr->m_cond.notify_one();
}
void* m_param;
uint64_t triggeredTime = UINT64_MAX;
bool active = true;
wpi::mutex mutex;
wpi::condition_variable cond;
};
} // namespace
static std::shared_ptr<Notifier> notifiers;
static std::atomic_flag notifierAtexitRegistered = ATOMIC_FLAG_INIT;
static std::atomic_flag notifierAtexitRegistered{ATOMIC_FLAG_INIT};
static std::atomic_int notifierRefCount{0};
using namespace hal;
static UnlimitedHandleResource<HAL_NotifierHandle, Notifier,
HAL_HandleEnum::Notifier>
notifierHandles;
// Internal version of updateAlarm used during the alarmCallback when we know
// that the pointer is a valid pointer. This function is synchronized by the
// caller locking notifierMutex.
void updateNotifierAlarmInternal(std::shared_ptr<Notifier> notifierPointer,
uint64_t triggerTime, int32_t* status) {
auto notifier = notifierPointer;
// no need for a null check, as this must always be a valid pointer.
notifier->triggerTime = triggerTime;
bool wasActive = (closestTrigger != UINT64_MAX);
if (!notifierInterruptMutex.try_lock() || notifierRefCount == 0 ||
!notifierAlarm)
return;
// Update alarm time if closer than current.
if (triggerTime < closestTrigger) {
closestTrigger = triggerTime;
// Simply truncate the hardware trigger time to 32-bit.
notifierAlarm->writeTriggerTime(static_cast<uint32_t>(triggerTime), status);
class NotifierHandleContainer
: public UnlimitedHandleResource<HAL_NotifierHandle, Notifier,
HAL_HandleEnum::Notifier> {
public:
~NotifierHandleContainer() {
ForEach([](HAL_NotifierHandle handle, Notifier* notifier) {
{
std::lock_guard<wpi::mutex> lock(notifier->mutex);
notifier->triggerTime = UINT64_MAX;
notifier->triggeredTime = 0;
notifier->active = false;
}
notifier->cond.notify_all(); // wake up any waiting threads
});
}
// Enable the alarm. The hardware disables itself after each alarm.
if (!wasActive) notifierAlarm->writeEnable(true, status);
};
notifierInterruptMutex.unlock();
}
static NotifierHandleContainer* notifierHandles;
static void alarmCallback(uint32_t, void*) {
std::unique_lock<std::mutex> sync(notifierMutex);
std::lock_guard<wpi::mutex> lock(notifierMutex);
int32_t status = 0;
uint64_t currentTime = 0;
@@ -135,22 +74,26 @@ static void alarmCallback(uint32_t, void*) {
closestTrigger = UINT64_MAX;
// process all notifiers
std::shared_ptr<Notifier> notifier = notifiers;
while (notifier) {
if (notifier->triggerTime != UINT64_MAX) {
if (currentTime == 0) currentTime = HAL_GetFPGATime(&status);
if (notifier->triggerTime < currentTime) {
notifier->triggerTime = UINT64_MAX;
auto process = notifier->process;
auto handle = notifier->handle;
sync.unlock();
process(currentTime, handle);
sync.lock();
} else if (notifier->triggerTime < closestTrigger) {
updateNotifierAlarmInternal(notifier, notifier->triggerTime, &status);
}
notifierHandles->ForEach([&](HAL_NotifierHandle handle, Notifier* notifier) {
if (notifier->triggerTime == UINT64_MAX) return;
if (currentTime == 0) currentTime = HAL_GetFPGATime(&status);
std::unique_lock<wpi::mutex> lock(notifier->mutex);
if (notifier->triggerTime < currentTime) {
notifier->triggerTime = UINT64_MAX;
notifier->triggeredTime = currentTime;
lock.unlock();
notifier->cond.notify_all();
} else if (notifier->triggerTime < closestTrigger) {
closestTrigger = notifier->triggerTime;
}
notifier = notifier->next;
});
if (notifierAlarm && closestTrigger != UINT64_MAX) {
// Simply truncate the hardware trigger time to 32-bit.
notifierAlarm->writeTriggerTime(static_cast<uint32_t>(closestTrigger),
&status);
// Enable the alarm. The hardware disables itself after each alarm.
notifierAlarm->writeEnable(true, &status);
}
}
@@ -159,30 +102,23 @@ static void cleanupNotifierAtExit() {
notifierManager = nullptr;
}
static void threadedNotifierHandler(uint64_t currentTimeInt,
HAL_NotifierHandle handle) {
// Grab notifier and get handler param
auto notifier = notifierHandles.Get(handle);
if (!notifier) return;
auto notifierPointer = notifier->param;
if (notifierPointer == nullptr) return;
NotifierThreadOwner* owner =
static_cast<NotifierThreadOwner*>(notifierPointer);
owner->Notify(currentTimeInt, handle);
namespace hal {
namespace init {
void InitializeNotifier() {
static NotifierHandleContainer nH;
notifierHandles = &nH;
}
} // namespace init
} // namespace hal
extern "C" {
HAL_NotifierHandle HAL_InitializeNotifierNonThreadedUnsafe(
HAL_NotifierProcessFunction process, void* param, int32_t* status) {
if (!process) {
*status = NULL_PARAMETER;
return 0;
}
HAL_NotifierHandle HAL_InitializeNotifier(int32_t* status) {
if (!notifierAtexitRegistered.test_and_set())
std::atexit(cleanupNotifierAtExit);
if (notifierRefCount.fetch_add(1) == 0) {
std::lock_guard<std::mutex> sync(notifierInterruptMutex);
std::lock_guard<wpi::mutex> lock(notifierMutex);
// create manager and alarm if not already created
if (!notifierManager) {
notifierManager = std::make_unique<tInterruptManager>(
@@ -193,107 +129,100 @@ HAL_NotifierHandle HAL_InitializeNotifierNonThreadedUnsafe(
if (!notifierAlarm) notifierAlarm.reset(tAlarm::create(status));
}
std::lock_guard<std::mutex> sync(notifierMutex);
std::shared_ptr<Notifier> notifier = std::make_shared<Notifier>();
HAL_NotifierHandle handle = notifierHandles.Allocate(notifier);
HAL_NotifierHandle handle = notifierHandles->Allocate(notifier);
if (handle == HAL_kInvalidHandle) {
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
}
// create notifier structure and add to list
notifier->next = notifiers;
if (notifier->next) notifier->next->prev = notifier;
notifier->param = param;
notifier->process = process;
notifier->handle = handle;
notifier->threaded = false;
notifiers = notifier;
return handle;
}
HAL_NotifierHandle HAL_InitializeNotifier(HAL_NotifierProcessFunction process,
void* param, int32_t* status) {
NotifierThreadOwner* notify = new NotifierThreadOwner;
notify->Start();
notify->SetFunc(process, param);
void HAL_StopNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
auto notifier = notifierHandles->Get(notifierHandle);
if (!notifier) return;
auto notifierHandle = HAL_InitializeNotifierNonThreadedUnsafe(
threadedNotifierHandler, notify, status);
if (notifierHandle == HAL_kInvalidHandle || *status != 0) {
delete notify;
return HAL_kInvalidHandle;
{
std::lock_guard<wpi::mutex> lock(notifier->mutex);
notifier->triggerTime = UINT64_MAX;
notifier->triggeredTime = 0;
notifier->active = false;
}
auto notifier = notifierHandles.Get(notifierHandle);
if (!notifier) {
return HAL_kInvalidHandle;
}
notifier->threaded = true;
return notifierHandle;
notifier->cond.notify_all(); // wake up any waiting threads
}
void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
auto notifier = notifierHandles->Free(notifierHandle);
if (!notifier) return;
// Just in case HAL_StopNotifier() wasn't called...
{
std::lock_guard<std::mutex> sync(notifierMutex);
auto notifier = notifierHandles.Get(notifierHandle);
if (!notifier) return;
// remove from list
if (notifier->prev) notifier->prev->next = notifier->next;
if (notifier->next) notifier->next->prev = notifier->prev;
if (notifiers == notifier) notifiers = notifier->next;
notifierHandles.Free(notifierHandle);
if (notifier->threaded) {
NotifierThreadOwner* owner =
static_cast<NotifierThreadOwner*>(notifier->param);
delete owner;
}
std::lock_guard<wpi::mutex> lock(notifier->mutex);
notifier->triggerTime = UINT64_MAX;
notifier->triggeredTime = 0;
notifier->active = false;
}
notifier->cond.notify_all();
if (notifierRefCount.fetch_sub(1) == 1) {
std::lock_guard<std::mutex> sync(notifierInterruptMutex);
// if this was the last notifier, clean up alarm and manager
if (notifierAlarm) {
notifierAlarm->writeEnable(false, status);
notifierAlarm = nullptr;
}
if (notifierManager) {
notifierManager->disable(status);
notifierManager = nullptr;
}
// the notifier can call back into our callback, so don't hold the lock
// here (the atomic fetch_sub will prevent multiple parallel entries
// into this function)
if (notifierAlarm) notifierAlarm->writeEnable(false, status);
if (notifierManager) notifierManager->disable(status);
std::lock_guard<wpi::mutex> lock(notifierMutex);
notifierAlarm = nullptr;
notifierManager = nullptr;
closestTrigger = UINT64_MAX;
}
}
void* HAL_GetNotifierParam(HAL_NotifierHandle notifierHandle, int32_t* status) {
auto notifier = notifierHandles.Get(notifierHandle);
if (!notifier) return nullptr;
if (notifier->threaded) {
// If threaded, return thread param rather then notifier param
NotifierThreadOwner* owner =
static_cast<NotifierThreadOwner*>(notifier->param);
return owner->m_param;
}
return notifier->param;
}
void HAL_UpdateNotifierAlarm(HAL_NotifierHandle notifierHandle,
uint64_t triggerTime, int32_t* status) {
std::lock_guard<std::mutex> sync(notifierMutex);
auto notifier = notifierHandles.Get(notifierHandle);
auto notifier = notifierHandles->Get(notifierHandle);
if (!notifier) return;
updateNotifierAlarmInternal(notifier, triggerTime, status);
{
std::lock_guard<wpi::mutex> lock(notifier->mutex);
notifier->triggerTime = triggerTime;
notifier->triggeredTime = UINT64_MAX;
}
std::lock_guard<wpi::mutex> lock(notifierMutex);
// Update alarm time if closer than current.
if (triggerTime < closestTrigger) {
bool wasActive = (closestTrigger != UINT64_MAX);
closestTrigger = triggerTime;
// Simply truncate the hardware trigger time to 32-bit.
notifierAlarm->writeTriggerTime(static_cast<uint32_t>(closestTrigger),
status);
// Enable the alarm.
if (!wasActive) notifierAlarm->writeEnable(true, status);
}
}
void HAL_StopNotifierAlarm(HAL_NotifierHandle notifierHandle, int32_t* status) {
std::lock_guard<std::mutex> sync(notifierMutex);
auto notifier = notifierHandles.Get(notifierHandle);
void HAL_CancelNotifierAlarm(HAL_NotifierHandle notifierHandle,
int32_t* status) {
auto notifier = notifierHandles->Get(notifierHandle);
if (!notifier) return;
notifier->triggerTime = UINT64_MAX;
{
std::lock_guard<wpi::mutex> lock(notifier->mutex);
notifier->triggerTime = UINT64_MAX;
}
}
uint64_t HAL_WaitForNotifierAlarm(HAL_NotifierHandle notifierHandle,
int32_t* status) {
auto notifier = notifierHandles->Get(notifierHandle);
if (!notifier) return 0;
std::unique_lock<wpi::mutex> lock(notifier->mutex);
notifier->cond.wait(lock, [&] {
return !notifier->active || notifier->triggeredTime != UINT64_MAX;
});
return notifier->active ? notifier->triggeredTime : 0;
}
} // extern "C"

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
@@ -24,6 +24,17 @@ static std::chrono::milliseconds portTimeouts[4]{
std::chrono::milliseconds(0), std::chrono::milliseconds(0),
std::chrono::milliseconds(0), std::chrono::milliseconds(0)};
namespace hal {
namespace init {
void InitializeOSSerialPort() {
for (int i = 0; i < 4; i++) {
portHandles[i] = -1;
portTimeouts[i] = std::chrono::milliseconds(0);
}
}
} // namespace init
} // namespace hal
extern "C" {
void HAL_InitializeOSSerialPort(HAL_SerialPort port, int32_t* status) {

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -16,6 +16,14 @@ 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) {
if (!HAL_CheckSolenoidModule(module)) {
*status = RESOURCE_OUT_OF_RANGE;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -31,6 +31,16 @@ static inline bool checkPDPInit(int32_t module, int32_t* status) {
return true;
}
namespace hal {
namespace init {
void InitializePDP() {
for (int i = 0; i < kNumPDPModules; i++) {
pdp[i] = nullptr;
}
}
} // namespace init
} // namespace hal
extern "C" {
void HAL_InitializePDP(int32_t module, int32_t* status) {

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -19,28 +19,49 @@ using namespace hal;
static inline int32_t GetMaxPositivePwm(DigitalPort* port) {
return port->maxPwm;
}
static inline int32_t GetMinPositivePwm(DigitalPort* port) {
return port->eliminateDeadband ? port->deadbandMaxPwm : port->centerPwm + 1;
if (port->eliminateDeadband) {
return port->deadbandMaxPwm;
} else {
return port->centerPwm + 1;
}
}
static inline int32_t GetCenterPwm(DigitalPort* port) {
return port->centerPwm;
}
static inline int32_t GetMaxNegativePwm(DigitalPort* port) {
return port->eliminateDeadband ? port->deadbandMinPwm : port->centerPwm - 1;
if (port->eliminateDeadband) {
return port->deadbandMinPwm;
} else {
return port->centerPwm - 1;
}
}
static inline int32_t GetMinNegativePwm(DigitalPort* port) {
return port->minPwm;
}
static inline int32_t GetPositiveScaleFactor(DigitalPort* port) {
return GetMaxPositivePwm(port) - GetMinPositivePwm(port);
} ///< The scale for positive speeds.
static inline int32_t GetNegativeScaleFactor(DigitalPort* port) {
return GetMaxNegativePwm(port) - GetMinNegativePwm(port);
} ///< The scale for negative speeds.
static inline int32_t GetFullRangeScaleFactor(DigitalPort* port) {
return GetMaxPositivePwm(port) - GetMinNegativePwm(port);
} ///< The scale for positions.
namespace hal {
namespace init {
void InitializePWM() {}
} // namespace init
} // namespace hal
extern "C" {
HAL_DigitalHandle HAL_InitializePWMPort(HAL_PortHandle portHandle,
@@ -64,12 +85,12 @@ HAL_DigitalHandle HAL_InitializePWMPort(HAL_PortHandle portHandle,
}
auto handle =
digitalChannelHandles.Allocate(channel, HAL_HandleEnum::PWM, status);
digitalChannelHandles->Allocate(channel, HAL_HandleEnum::PWM, status);
if (*status != 0)
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
auto port = digitalChannelHandles.Get(handle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(handle, HAL_HandleEnum::PWM);
if (port == nullptr) { // would only occur on thread issue.
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
@@ -86,7 +107,7 @@ HAL_DigitalHandle HAL_InitializePWMPort(HAL_PortHandle portHandle,
return handle;
}
void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -100,7 +121,7 @@ void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
status);
}
digitalChannelHandles.Free(pwmPortHandle, HAL_HandleEnum::PWM);
digitalChannelHandles->Free(pwmPortHandle, HAL_HandleEnum::PWM);
}
HAL_Bool HAL_CheckPWMChannel(int32_t channel) {
@@ -110,7 +131,7 @@ HAL_Bool HAL_CheckPWMChannel(int32_t channel) {
void HAL_SetPWMConfig(HAL_DigitalHandle pwmPortHandle, double max,
double deadbandMax, double center, double deadbandMin,
double min, int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -144,7 +165,7 @@ void HAL_SetPWMConfigRaw(HAL_DigitalHandle pwmPortHandle, int32_t maxPwm,
int32_t deadbandMaxPwm, int32_t centerPwm,
int32_t deadbandMinPwm, int32_t minPwm,
int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -161,7 +182,7 @@ void HAL_GetPWMConfigRaw(HAL_DigitalHandle pwmPortHandle, int32_t* maxPwm,
int32_t* deadbandMaxPwm, int32_t* centerPwm,
int32_t* deadbandMinPwm, int32_t* minPwm,
int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -175,7 +196,7 @@ void HAL_GetPWMConfigRaw(HAL_DigitalHandle pwmPortHandle, int32_t* maxPwm,
void HAL_SetPWMEliminateDeadband(HAL_DigitalHandle pwmPortHandle,
HAL_Bool eliminateDeadband, int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -185,7 +206,7 @@ void HAL_SetPWMEliminateDeadband(HAL_DigitalHandle pwmPortHandle,
HAL_Bool HAL_GetPWMEliminateDeadband(HAL_DigitalHandle pwmPortHandle,
int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
@@ -203,7 +224,7 @@ HAL_Bool HAL_GetPWMEliminateDeadband(HAL_DigitalHandle pwmPortHandle,
*/
void HAL_SetPWMRaw(HAL_DigitalHandle pwmPortHandle, int32_t value,
int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -227,7 +248,7 @@ void HAL_SetPWMRaw(HAL_DigitalHandle pwmPortHandle, int32_t value,
*/
void HAL_SetPWMSpeed(HAL_DigitalHandle pwmPortHandle, double speed,
int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -282,7 +303,7 @@ void HAL_SetPWMSpeed(HAL_DigitalHandle pwmPortHandle, double speed,
*/
void HAL_SetPWMPosition(HAL_DigitalHandle pwmPortHandle, double pos,
int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -324,7 +345,7 @@ void HAL_SetPWMDisabled(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
* @return The raw PWM value.
*/
int32_t HAL_GetPWMRaw(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -344,7 +365,7 @@ int32_t HAL_GetPWMRaw(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
* @return The scaled PWM value.
*/
double HAL_GetPWMSpeed(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -382,7 +403,7 @@ double HAL_GetPWMSpeed(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
* @return The scaled PWM value.
*/
double HAL_GetPWMPosition(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
@@ -407,7 +428,7 @@ double HAL_GetPWMPosition(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
}
void HAL_LatchPWMZero(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -425,7 +446,7 @@ void HAL_LatchPWMZero(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
*/
void HAL_SetPWMPeriodScale(HAL_DigitalHandle pwmPortHandle, int32_t squelchMask,
int32_t* status) {
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -458,6 +479,7 @@ int32_t HAL_GetPWMLoopTiming(int32_t* status) {
uint64_t HAL_GetPWMCycleStartTime(int32_t* status) {
initializeDigital(status);
if (*status != 0) return 0;
uint64_t upper1 = pwmSystem->readCycleStartTimeUpper(status);
uint32_t lower = pwmSystem->readCycleStartTime(status);
uint64_t upper2 = pwmSystem->readCycleStartTimeUpper(status);

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,6 +11,12 @@
using namespace hal;
namespace hal {
namespace init {
void InitializePorts() {}
} // namespace init
} // namespace hal
extern "C" {
int32_t HAL_GetNumAccumulators(void) { return kNumAccumulators; }

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -15,7 +15,7 @@ using namespace hal;
namespace hal {
static std::unique_ptr<tPower> power;
static std::unique_ptr<tPower> power{nullptr};
static void initializePower(int32_t* status) {
if (power == nullptr) {
@@ -25,6 +25,12 @@ static void initializePower(int32_t* status) {
} // namespace hal
namespace hal {
namespace init {
void InitializePower() {}
} // namespace init
} // namespace hal
extern "C" {
/**

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -23,11 +23,21 @@ struct Relay {
} // namespace
static IndexedHandleResource<HAL_RelayHandle, Relay, kNumRelayChannels,
HAL_HandleEnum::Relay>
relayHandles;
HAL_HandleEnum::Relay>* relayHandles;
// Create a mutex to protect changes to the relay values
static std::mutex digitalRelayMutex;
static wpi::mutex digitalRelayMutex;
namespace hal {
namespace init {
void InitializeRelay() {
static IndexedHandleResource<HAL_RelayHandle, Relay, kNumRelayChannels,
HAL_HandleEnum::Relay>
rH;
relayHandles = &rH;
}
} // namespace init
} // namespace hal
extern "C" {
@@ -45,12 +55,12 @@ HAL_RelayHandle HAL_InitializeRelayPort(HAL_PortHandle portHandle, HAL_Bool fwd,
if (!fwd) channel += kNumRelayHeaders; // add 4 to reverse channels
auto handle = relayHandles.Allocate(channel, status);
auto handle = relayHandles->Allocate(channel, status);
if (*status != 0)
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
auto port = relayHandles.Get(handle);
auto port = relayHandles->Get(handle);
if (port == nullptr) { // would only occur on thread issue.
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
@@ -71,7 +81,7 @@ HAL_RelayHandle HAL_InitializeRelayPort(HAL_PortHandle portHandle, HAL_Bool fwd,
void HAL_FreeRelayPort(HAL_RelayHandle relayPortHandle) {
// no status, so no need to check for a proper free.
relayHandles.Free(relayPortHandle);
relayHandles->Free(relayPortHandle);
}
HAL_Bool HAL_CheckRelayChannel(int32_t channel) {
@@ -87,12 +97,12 @@ HAL_Bool HAL_CheckRelayChannel(int32_t channel) {
*/
void HAL_SetRelay(HAL_RelayHandle relayPortHandle, HAL_Bool on,
int32_t* status) {
auto port = relayHandles.Get(relayPortHandle);
auto port = relayHandles->Get(relayPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
std::lock_guard<std::mutex> sync(digitalRelayMutex);
std::lock_guard<wpi::mutex> lock(digitalRelayMutex);
uint8_t relays = 0;
if (port->fwd) {
relays = relaySystem->readValue_Forward(status);
@@ -119,7 +129,7 @@ void HAL_SetRelay(HAL_RelayHandle relayPortHandle, HAL_Bool on,
* Get the current state of the relay channel
*/
HAL_Bool HAL_GetRelay(HAL_RelayHandle relayPortHandle, int32_t* status) {
auto port = relayHandles.Get(relayPortHandle);
auto port = relayHandles->Get(relayPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -7,67 +7,67 @@
#include "HAL/SPI.h"
#include <fcntl.h>
#include <linux/spi/spidev.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <array>
#include <atomic>
#include <mutex>
#include <cstring>
#include <llvm/raw_ostream.h>
#include <spilib/spi-lib.h>
#include <support/mutex.h>
#include "DigitalInternal.h"
#include "HAL/DIO.h"
#include "HAL/HAL.h"
#include "HAL/Notifier.h"
#include "HAL/cpp/make_unique.h"
#include "HAL/handles/HandlesInternal.h"
using namespace hal;
static int32_t m_spiCS0Handle = 0;
static int32_t m_spiCS1Handle = 0;
static int32_t m_spiCS2Handle = 0;
static int32_t m_spiCS3Handle = 0;
static int32_t m_spiMXPHandle = 0;
static int32_t m_spiCS0Handle{0};
static int32_t m_spiCS1Handle{0};
static int32_t m_spiCS2Handle{0};
static int32_t m_spiCS3Handle{0};
static int32_t m_spiMXPHandle{0};
static constexpr int32_t kSpiMaxHandles = 5;
// Indices 0-3 are for onboard CS0-CS2. Index 4 is for MXP.
static std::array<std::mutex, kSpiMaxHandles> spiHandleMutexes;
static std::array<std::mutex, kSpiMaxHandles> spiApiMutexes;
static std::array<std::mutex, kSpiMaxHandles> spiAccumulatorMutexes;
static std::array<wpi::mutex, kSpiMaxHandles> spiHandleMutexes;
static std::array<wpi::mutex, kSpiMaxHandles> spiApiMutexes;
static std::array<wpi::mutex, kSpiMaxHandles> spiAccumulatorMutexes;
// MXP SPI does not count towards this
std::atomic<int32_t> spiPortCount{0};
static std::atomic<int32_t> spiPortCount{0};
static HAL_DigitalHandle digitalHandles[9]{HAL_kInvalidHandle};
static wpi::mutex spiAutoMutex;
static int32_t spiAutoPort = kSpiMaxHandles;
static std::atomic_bool spiAutoRunning{false};
static std::unique_ptr<tDMAManager> spiAutoDMA;
static bool SPIInUseByAuto(HAL_SPIPort port) {
// 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;
std::lock_guard<wpi::mutex> lock(spiAutoMutex);
return (spiAutoPort >= 0 && spiAutoPort <= 3 && port >= 0 && port <= 3) ||
(spiAutoPort == 4 && port == 4);
}
namespace hal {
namespace init {
void InitializeSPI() {}
} // namespace init
} // namespace hal
extern "C" {
struct SPIAccumulator {
std::atomic<HAL_NotifierHandle> notifier{0};
uint64_t triggerTime;
int32_t period;
int64_t value = 0;
uint32_t count = 0;
int32_t lastValue = 0;
int32_t center = 0;
int32_t deadband = 0;
uint8_t cmd[4]; // command to send (up to 4 bytes)
int32_t validMask;
int32_t validValue;
int32_t dataMax; // one more than max data value
int32_t dataMsbMask; // data field MSB mask (for signed)
uint8_t dataShift; // data field shift right amount, in bits
uint8_t xferSize; // SPI transfer size, in bytes (up to 4)
HAL_SPIPort port;
bool isSigned; // is data field signed?
bool bigEndian; // is response big endian?
};
std::unique_ptr<SPIAccumulator> spiAccumulators[5];
static void CommonSPIPortInit(int32_t* status) {
// All false cases will set
if (spiPortCount.fetch_add(1) == 0) {
@@ -92,7 +92,7 @@ static void CommonSPIPortInit(int32_t* status) {
}
}
static void CommonSPIPortFree() {
static void CommonSPIPortFree(void) {
if (spiPortCount.fetch_sub(1) == 1) {
// Clean up SPI Handles
HAL_FreeDIOPort(digitalHandles[3]);
@@ -111,13 +111,21 @@ void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) {
return;
}
int handle;
if (HAL_GetSPIHandle(port) != 0) return;
switch (port) {
case 0:
CommonSPIPortInit(status);
if (*status != 0) return;
// CS0 is not a DIO port, so nothing to allocate
HAL_SetSPIHandle(HAL_SPI_kOnboardCS0, spilib_open("/dev/spidev0.0"));
handle = open("/dev/spidev0.0", O_RDWR);
if (handle < 0) {
std::printf("Failed to open SPI port %d: %s\n", port,
std::strerror(errno));
CommonSPIPortFree();
return;
}
HAL_SetSPIHandle(HAL_SPI_kOnboardCS0, handle);
break;
case 1:
CommonSPIPortInit(status);
@@ -130,7 +138,15 @@ void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) {
CommonSPIPortFree();
return;
}
HAL_SetSPIHandle(HAL_SPI_kOnboardCS1, spilib_open("/dev/spidev0.1"));
handle = open("/dev/spidev0.1", O_RDWR);
if (handle < 0) {
std::printf("Failed to open SPI port %d: %s\n", port,
std::strerror(errno));
CommonSPIPortFree();
HAL_FreeDIOPort(digitalHandles[0]);
return;
}
HAL_SetSPIHandle(HAL_SPI_kOnboardCS1, handle);
break;
case 2:
CommonSPIPortInit(status);
@@ -143,7 +159,15 @@ void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) {
CommonSPIPortFree();
return;
}
HAL_SetSPIHandle(HAL_SPI_kOnboardCS2, spilib_open("/dev/spidev0.2"));
handle = open("/dev/spidev0.2", O_RDWR);
if (handle < 0) {
std::printf("Failed to open SPI port %d: %s\n", port,
std::strerror(errno));
CommonSPIPortFree();
HAL_FreeDIOPort(digitalHandles[1]);
return;
}
HAL_SetSPIHandle(HAL_SPI_kOnboardCS2, handle);
break;
case 3:
CommonSPIPortInit(status);
@@ -156,7 +180,15 @@ void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) {
CommonSPIPortFree();
return;
}
HAL_SetSPIHandle(HAL_SPI_kOnboardCS3, spilib_open("/dev/spidev0.3"));
handle = open("/dev/spidev0.3", O_RDWR);
if (handle < 0) {
std::printf("Failed to open SPI port %d: %s\n", port,
std::strerror(errno));
CommonSPIPortFree();
HAL_FreeDIOPort(digitalHandles[2]);
return;
}
HAL_SetSPIHandle(HAL_SPI_kOnboardCS3, handle);
break;
case 4:
initializeDigital(status);
@@ -193,13 +225,22 @@ void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) {
}
digitalSystem->writeEnableMXPSpecialFunction(
digitalSystem->readEnableMXPSpecialFunction(status) | 0x00F0, status);
HAL_SetSPIHandle(HAL_SPI_kMXP, spilib_open("/dev/spidev1.0"));
handle = open("/dev/spidev1.0", O_RDWR);
if (handle < 0) {
std::printf("Failed to open SPI port %d: %s\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
HAL_FreeDIOPort(digitalHandles[8]); // free the fourth port allocated
return;
}
HAL_SetSPIHandle(HAL_SPI_kMXP, handle);
break;
default:
*status = PARAMETER_OUT_OF_RANGE;
break;
}
return;
}
/**
@@ -214,16 +255,22 @@ void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) {
* @param size Number of bytes to transfer. [0..7]
* @return Number of bytes transferred, -1 for error
*/
int32_t HAL_TransactionSPI(HAL_SPIPort port, uint8_t* dataToSend,
int32_t HAL_TransactionSPI(HAL_SPIPort port, const uint8_t* dataToSend,
uint8_t* dataReceived, int32_t size) {
if (port < 0 || port >= kSpiMaxHandles) {
return -1;
}
std::lock_guard<std::mutex> sync(spiApiMutexes[port]);
return spilib_writeread(
HAL_GetSPIHandle(port), reinterpret_cast<const char*>(dataToSend),
reinterpret_cast<char*>(dataReceived), static_cast<int32_t>(size));
if (SPIInUseByAuto(port)) return -1;
struct spi_ioc_transfer xfer;
std::memset(&xfer, 0, sizeof(xfer));
xfer.tx_buf = (__u64)dataToSend;
xfer.rx_buf = (__u64)dataReceived;
xfer.len = size;
std::lock_guard<wpi::mutex> lock(spiApiMutexes[port]);
return ioctl(HAL_GetSPIHandle(port), SPI_IOC_MESSAGE(1), &xfer);
}
/**
@@ -236,15 +283,21 @@ int32_t HAL_TransactionSPI(HAL_SPIPort port, uint8_t* dataToSend,
* @param sendSize The number of bytes to be written
* @return The number of bytes written. -1 for an error
*/
int32_t HAL_WriteSPI(HAL_SPIPort port, uint8_t* dataToSend, int32_t sendSize) {
int32_t HAL_WriteSPI(HAL_SPIPort port, const uint8_t* dataToSend,
int32_t sendSize) {
if (port < 0 || port >= kSpiMaxHandles) {
return -1;
}
std::lock_guard<std::mutex> sync(spiApiMutexes[port]);
return spilib_write(HAL_GetSPIHandle(port),
reinterpret_cast<const char*>(dataToSend),
static_cast<int32_t>(sendSize));
if (SPIInUseByAuto(port)) return -1;
struct spi_ioc_transfer xfer;
std::memset(&xfer, 0, sizeof(xfer));
xfer.tx_buf = (__u64)dataToSend;
xfer.len = sendSize;
std::lock_guard<wpi::mutex> lock(spiApiMutexes[port]);
return ioctl(HAL_GetSPIHandle(port), SPI_IOC_MESSAGE(1), &xfer);
}
/**
@@ -265,9 +318,15 @@ int32_t HAL_ReadSPI(HAL_SPIPort port, uint8_t* buffer, int32_t count) {
return -1;
}
std::lock_guard<std::mutex> sync(spiApiMutexes[port]);
return spilib_read(HAL_GetSPIHandle(port), reinterpret_cast<char*>(buffer),
static_cast<int32_t>(count));
if (SPIInUseByAuto(port)) return -1;
struct spi_ioc_transfer xfer;
std::memset(&xfer, 0, sizeof(xfer));
xfer.rx_buf = (__u64)buffer;
xfer.len = count;
std::lock_guard<wpi::mutex> lock(spiApiMutexes[port]);
return ioctl(HAL_GetSPIHandle(port), SPI_IOC_MESSAGE(1), &xfer);
}
/**
@@ -281,11 +340,11 @@ void HAL_CloseSPI(HAL_SPIPort port) {
}
int32_t status = 0;
HAL_FreeSPIAccumulator(port, &status);
HAL_FreeSPIAuto(port, &status);
{
std::lock_guard<std::mutex> sync(spiApiMutexes[port]);
spilib_close(HAL_GetSPIHandle(port));
std::lock_guard<wpi::mutex> lock(spiApiMutexes[port]);
close(HAL_GetSPIHandle(port));
}
HAL_SetSPIHandle(port, 0);
@@ -326,8 +385,8 @@ void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed) {
return;
}
std::lock_guard<std::mutex> sync(spiApiMutexes[port]);
spilib_setspeed(HAL_GetSPIHandle(port), speed);
std::lock_guard<wpi::mutex> lock(spiApiMutexes[port]);
ioctl(HAL_GetSPIHandle(port), SPI_IOC_WR_MAX_SPEED_HZ, &speed);
}
/**
@@ -346,9 +405,13 @@ void HAL_SetSPIOpts(HAL_SPIPort port, HAL_Bool msbFirst,
return;
}
std::lock_guard<std::mutex> sync(spiApiMutexes[port]);
spilib_setopts(HAL_GetSPIHandle(port), msbFirst, sampleOnTrailing,
clkIdleHigh);
uint8_t mode = 0;
mode |= (!msbFirst ? 8 : 0);
mode |= (clkIdleHigh ? 2 : 0);
mode |= (sampleOnTrailing ? 1 : 0);
std::lock_guard<wpi::mutex> lock(spiApiMutexes[port]);
ioctl(HAL_GetSPIHandle(port), SPI_IOC_WR_MODE, &mode);
}
/**
@@ -362,7 +425,7 @@ void HAL_SetSPIChipSelectActiveHigh(HAL_SPIPort port, int32_t* status) {
return;
}
std::lock_guard<std::mutex> sync(spiApiMutexes[port]);
std::lock_guard<wpi::mutex> lock(spiApiMutexes[port]);
if (port < 4) {
spiSystem->writeChipSelectActiveHigh_Hdr(
spiSystem->readChipSelectActiveHigh_Hdr(status) | (1 << port), status);
@@ -382,7 +445,7 @@ void HAL_SetSPIChipSelectActiveLow(HAL_SPIPort port, int32_t* status) {
return;
}
std::lock_guard<std::mutex> sync(spiApiMutexes[port]);
std::lock_guard<wpi::mutex> lock(spiApiMutexes[port]);
if (port < 4) {
spiSystem->writeChipSelectActiveHigh_Hdr(
spiSystem->readChipSelectActiveHigh_Hdr(status) & ~(1 << port), status);
@@ -402,7 +465,7 @@ int32_t HAL_GetSPIHandle(HAL_SPIPort port) {
return 0;
}
std::lock_guard<std::mutex> sync(spiHandleMutexes[port]);
std::lock_guard<wpi::mutex> lock(spiHandleMutexes[port]);
switch (port) {
case 0:
return m_spiCS0Handle;
@@ -431,7 +494,7 @@ void HAL_SetSPIHandle(HAL_SPIPort port, int32_t handle) {
return;
}
std::lock_guard<std::mutex> sync(spiHandleMutexes[port]);
std::lock_guard<wpi::mutex> lock(spiHandleMutexes[port]);
switch (port) {
case 0:
m_spiCS0Handle = handle;
@@ -453,317 +516,202 @@ void HAL_SetSPIHandle(HAL_SPIPort port, int32_t handle) {
}
}
static void spiAccumulatorProcess(uint64_t currentTime,
HAL_NotifierHandle handle) {
int32_t status = 0;
auto param = HAL_GetNotifierParam(handle, &status);
if (param == nullptr) return;
SPIAccumulator* accum = static_cast<SPIAccumulator*>(param);
// perform SPI transaction
uint8_t resp_b[4];
{
std::lock_guard<std::mutex> sync(spiApiMutexes[accum->port]);
spilib_writeread(HAL_GetSPIHandle(accum->port),
reinterpret_cast<const char*>(accum->cmd),
reinterpret_cast<char*>(resp_b),
static_cast<int32_t>(accum->xferSize));
void HAL_InitSPIAuto(HAL_SPIPort port, int32_t bufferSize, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
return;
}
// convert from bytes
uint32_t resp = 0;
if (accum->bigEndian) {
for (int32_t i = 0; i < accum->xferSize; ++i) {
resp <<= 8;
resp |= resp_b[i] & 0xff;
}
std::lock_guard<wpi::mutex> lock(spiAutoMutex);
// FPGA only has one auto SPI engine
if (spiAutoPort != kSpiMaxHandles) {
*status = RESOURCE_IS_ALLOCATED;
return;
}
// remember the initialized port for other entry points
spiAutoPort = port;
// configure the correct chip select
if (port < 4) {
spiSystem->writeAutoSPI1Select(false, status);
spiSystem->writeAutoChipSelect(port, status);
} else {
for (int32_t i = accum->xferSize - 1; i >= 0; --i) {
resp <<= 8;
resp |= resp_b[i] & 0xff;
}
spiSystem->writeAutoSPI1Select(true, status);
spiSystem->writeAutoChipSelect(0, status);
}
// process response
if ((resp & accum->validMask) == static_cast<uint32_t>(accum->validValue)) {
// valid sensor data; extract data field
int32_t data = static_cast<int32_t>(resp >> accum->dataShift);
data &= accum->dataMax - 1;
// 2s complement conversion if signed MSB is set
if (accum->isSigned && (data & accum->dataMsbMask) != 0)
data -= accum->dataMax;
// center offset
data -= accum->center;
// only accumulate if outside deadband
if (data < -accum->deadband || data > accum->deadband) accum->value += data;
++accum->count;
accum->lastValue = data;
} else {
// no data from the sensor; just clear the last value
accum->lastValue = 0;
}
// reschedule timer
accum->triggerTime += accum->period;
// handle timer slip
if (accum->triggerTime < currentTime)
accum->triggerTime = currentTime + accum->period;
status = 0;
HAL_UpdateNotifierAlarm(accum->notifier, accum->triggerTime, &status);
// configure DMA
tDMAChannelDescriptor desc;
spiSystem->getSystemInterface()->getDmaDescriptor(g_SpiAutoData_index, &desc);
spiAutoDMA = std::make_unique<tDMAManager>(desc.channel, bufferSize, status);
}
/**
* Initialize a SPI accumulator.
*
* @param port SPI port
* @param period Time between reads, in us
* @param cmd SPI command to send to request data
* @param xferSize SPI transfer size, in bytes
* @param validMask Mask to apply to received data for validity checking
* @param valid_data After validMask is applied, required matching value for
* validity checking
* @param dataShift Bit shift to apply to received data to get actual data
* value
* @param dataSize Size (in bits) of data field
* @param isSigned Is data field signed?
* @param bigEndian Is device big endian?
*/
void HAL_InitSPIAccumulator(HAL_SPIPort port, int32_t period, int32_t cmd,
int32_t xferSize, int32_t validMask,
int32_t validValue, int32_t dataShift,
int32_t dataSize, HAL_Bool isSigned,
HAL_Bool bigEndian, int32_t* status) {
void HAL_FreeSPIAuto(HAL_SPIPort port, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
return;
}
std::lock_guard<std::mutex> sync(spiAccumulatorMutexes[port]);
if (!spiAccumulators[port])
spiAccumulators[port] = std::make_unique<SPIAccumulator>();
SPIAccumulator* accum = spiAccumulators[port].get();
if (bigEndian) {
for (int32_t i = xferSize - 1; i >= 0; --i) {
accum->cmd[i] = cmd & 0xff;
cmd >>= 8;
}
} else {
accum->cmd[0] = cmd & 0xff;
cmd >>= 8;
accum->cmd[1] = cmd & 0xff;
cmd >>= 8;
accum->cmd[2] = cmd & 0xff;
cmd >>= 8;
accum->cmd[3] = cmd & 0xff;
}
accum->period = period;
accum->xferSize = xferSize;
accum->validMask = validMask;
accum->validValue = validValue;
accum->dataShift = dataShift;
accum->dataMax = (1 << dataSize);
accum->dataMsbMask = (1 << (dataSize - 1));
accum->isSigned = isSigned;
accum->bigEndian = bigEndian;
accum->port = port;
if (!accum->notifier) {
accum->notifier =
HAL_InitializeNotifier(spiAccumulatorProcess, accum, status);
accum->triggerTime = HAL_GetFPGATime(status) + period;
if (*status != 0) return;
HAL_UpdateNotifierAlarm(accum->notifier, accum->triggerTime, status);
}
std::lock_guard<wpi::mutex> lock(spiAutoMutex);
if (spiAutoPort != port) return;
spiAutoPort = kSpiMaxHandles;
// disable by setting to internal clock and setting rate=0
spiSystem->writeAutoRate(0, status);
spiSystem->writeAutoTriggerConfig_ExternalClock(false, status);
// stop the DMA
spiAutoDMA->stop(status);
spiAutoDMA.reset(nullptr);
spiAutoRunning = false;
}
/**
* Frees a SPI accumulator.
*/
void HAL_FreeSPIAccumulator(HAL_SPIPort port, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
void HAL_StartSPIAutoRate(HAL_SPIPort port, double period, int32_t* status) {
std::lock_guard<wpi::mutex> lock(spiAutoMutex);
// FPGA only has one auto SPI engine
if (port != spiAutoPort) {
*status = INCOMPATIBLE_STATE;
return;
}
spiAutoRunning = true;
// start the DMA
spiAutoDMA->start(status);
// auto rate is in microseconds
spiSystem->writeAutoRate(period * 1000000, status);
// disable the external clock
spiSystem->writeAutoTriggerConfig_ExternalClock(false, status);
}
void HAL_StartSPIAutoTrigger(HAL_SPIPort port, HAL_Handle digitalSourceHandle,
HAL_AnalogTriggerType analogTriggerType,
HAL_Bool triggerRising, HAL_Bool triggerFalling,
int32_t* status) {
std::lock_guard<wpi::mutex> lock(spiAutoMutex);
// FPGA only has one auto SPI engine
if (port != spiAutoPort) {
*status = INCOMPATIBLE_STATE;
return;
}
spiAutoRunning = true;
// start the DMA
spiAutoDMA->start(status);
// get channel routing
bool routingAnalogTrigger = false;
uint8_t routingChannel = 0;
uint8_t routingModule = 0;
if (!remapDigitalSource(digitalSourceHandle, analogTriggerType,
routingChannel, routingModule,
routingAnalogTrigger)) {
*status = HAL_HANDLE_ERROR;
return;
}
// configure external trigger and enable it
tSPI::tAutoTriggerConfig config;
config.ExternalClock = 1;
config.FallingEdge = triggerFalling ? 1 : 0;
config.RisingEdge = triggerRising ? 1 : 0;
config.ExternalClockSource_AnalogTrigger = routingAnalogTrigger ? 1 : 0;
config.ExternalClockSource_Module = routingModule;
config.ExternalClockSource_Channel = routingChannel;
spiSystem->writeAutoTriggerConfig(config, status);
}
void HAL_StopSPIAuto(HAL_SPIPort port, int32_t* status) {
std::lock_guard<wpi::mutex> lock(spiAutoMutex);
// FPGA only has one auto SPI engine
if (port != spiAutoPort) {
*status = INCOMPATIBLE_STATE;
return;
}
// disable by setting to internal clock and setting rate=0
spiSystem->writeAutoRate(0, status);
spiSystem->writeAutoTriggerConfig_ExternalClock(false, status);
// stop the DMA
spiAutoDMA->stop(status);
spiAutoRunning = false;
}
void HAL_SetSPIAutoTransmitData(HAL_SPIPort port, const uint8_t* dataToSend,
int32_t dataSize, int32_t zeroSize,
int32_t* status) {
if (dataSize < 0 || dataSize > 16) {
*status = PARAMETER_OUT_OF_RANGE;
return;
}
std::lock_guard<std::mutex> sync(spiAccumulatorMutexes[port]);
SPIAccumulator* accum = spiAccumulators[port].get();
if (!accum) {
*status = NULL_PARAMETER;
return;
}
HAL_NotifierHandle handle = accum->notifier.exchange(0);
HAL_CleanNotifier(handle, status);
spiAccumulators[port] = nullptr;
}
/**
* Resets the accumulator to zero.
*/
void HAL_ResetSPIAccumulator(HAL_SPIPort port, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
if (zeroSize < 0 || zeroSize > 127) {
*status = PARAMETER_OUT_OF_RANGE;
return;
}
std::lock_guard<std::mutex> sync(spiApiMutexes[port]);
SPIAccumulator* accum = spiAccumulators[port].get();
if (!accum) {
*status = NULL_PARAMETER;
std::lock_guard<wpi::mutex> lock(spiAutoMutex);
// FPGA only has one auto SPI engine
if (port != spiAutoPort) {
*status = INCOMPATIBLE_STATE;
return;
}
accum->value = 0;
accum->count = 0;
accum->lastValue = 0;
// set tx data registers
for (int32_t i = 0; i < dataSize; ++i)
spiSystem->writeAutoTx(i >> 2, i & 3, dataToSend[i], status);
// set byte counts
tSPI::tAutoByteCount config;
config.ZeroByteCount = static_cast<unsigned>(zeroSize) & 0x7f;
config.TxByteCount = static_cast<unsigned>(dataSize) & 0xf;
spiSystem->writeAutoByteCount(config, status);
}
/**
* Set the center value of the accumulator.
*
* The center value is subtracted from each value before it is added to the
* accumulator. This
* is used for the center value of devices like gyros and accelerometers to make
* integration work
* and to take the device offset into account when integrating.
*/
void HAL_SetSPIAccumulatorCenter(HAL_SPIPort port, int32_t center,
int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
void HAL_ForceSPIAutoRead(HAL_SPIPort port, int32_t* status) {
std::lock_guard<wpi::mutex> lock(spiAutoMutex);
// FPGA only has one auto SPI engine
if (port != spiAutoPort) {
*status = INCOMPATIBLE_STATE;
return;
}
std::lock_guard<std::mutex> sync(spiAccumulatorMutexes[port]);
SPIAccumulator* accum = spiAccumulators[port].get();
if (!accum) {
*status = NULL_PARAMETER;
return;
}
accum->center = center;
spiSystem->strobeAutoForceOne(status);
}
/**
* Set the accumulator's deadband.
*/
void HAL_SetSPIAccumulatorDeadband(HAL_SPIPort port, int32_t deadband,
int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
return;
}
std::lock_guard<std::mutex> sync(spiAccumulatorMutexes[port]);
SPIAccumulator* accum = spiAccumulators[port].get();
if (!accum) {
*status = NULL_PARAMETER;
return;
}
accum->deadband = deadband;
}
/**
* Read the last value read by the accumulator engine.
*/
int32_t HAL_GetSPIAccumulatorLastValue(HAL_SPIPort port, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
int32_t HAL_ReadSPIAutoReceivedData(HAL_SPIPort port, uint8_t* buffer,
int32_t numToRead, double timeout,
int32_t* status) {
std::lock_guard<wpi::mutex> lock(spiAutoMutex);
// FPGA only has one auto SPI engine
if (port != spiAutoPort) {
*status = INCOMPATIBLE_STATE;
return 0;
}
std::lock_guard<std::mutex> sync(spiAccumulatorMutexes[port]);
SPIAccumulator* accum = spiAccumulators[port].get();
if (!accum) {
*status = NULL_PARAMETER;
return 0;
}
return accum->lastValue;
size_t numRemaining = 0;
// timeout is in ms
spiAutoDMA->read(buffer, numToRead, timeout * 1000, &numRemaining, status);
return numRemaining;
}
/**
* Read the accumulated value.
*
* @return The 64-bit value accumulated since the last Reset().
*/
int64_t HAL_GetSPIAccumulatorValue(HAL_SPIPort port, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
int32_t HAL_GetSPIAutoDroppedCount(HAL_SPIPort port, int32_t* status) {
std::lock_guard<wpi::mutex> lock(spiAutoMutex);
// FPGA only has one auto SPI engine
if (port != spiAutoPort) {
*status = INCOMPATIBLE_STATE;
return 0;
}
std::lock_guard<std::mutex> sync(spiAccumulatorMutexes[port]);
SPIAccumulator* accum = spiAccumulators[port].get();
if (!accum) {
*status = NULL_PARAMETER;
return 0;
}
return accum->value;
}
/**
* Read the number of accumulated values.
*
* Read the count of the accumulated values since the accumulator was last
* Reset().
*
* @return The number of times samples from the channel were accumulated.
*/
int64_t HAL_GetSPIAccumulatorCount(HAL_SPIPort port, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
return 0;
}
std::lock_guard<std::mutex> sync(spiAccumulatorMutexes[port]);
SPIAccumulator* accum = spiAccumulators[port].get();
if (!accum) {
*status = NULL_PARAMETER;
return 0;
}
return accum->count;
}
/**
* Read the average of the accumulated value.
*
* @return The accumulated average value (value / count).
*/
double HAL_GetSPIAccumulatorAverage(HAL_SPIPort port, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
return 0.0;
}
int64_t value;
int64_t count;
HAL_GetSPIAccumulatorOutput(port, &value, &count, status);
if (count == 0) return 0.0;
return static_cast<double>(value) / count;
}
/**
* Read the accumulated value and the number of accumulated values atomically.
*
* This function reads the value and count atomically.
* This can be used for averaging.
*
* @param value Pointer to the 64-bit accumulated output.
* @param count Pointer to the number of accumulation cycles.
*/
void HAL_GetSPIAccumulatorOutput(HAL_SPIPort port, int64_t* value,
int64_t* count, int32_t* status) {
if (port < 0 || port >= kSpiMaxHandles) {
*status = PARAMETER_OUT_OF_RANGE;
return;
}
std::lock_guard<std::mutex> sync(spiAccumulatorMutexes[port]);
SPIAccumulator* accum = spiAccumulators[port].get();
if (!accum) {
*status = NULL_PARAMETER;
*value = 0;
*count = 0;
return;
}
*value = accum->value;
*count = accum->count;
return spiSystem->readTransferSkippedFullCount(status);
}
} // extern "C"

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -12,9 +12,15 @@
#include "HAL/cpp/SerialHelper.h"
#include "visa/visa.h"
static int32_t resourceManagerHandle;
static int32_t resourceManagerHandle{0};
static HAL_SerialPort portHandles[4];
namespace hal {
namespace init {
void InitializeSerialPort() {}
} // namespace init
} // namespace hal
extern "C" {
void HAL_InitializeSerialPort(HAL_SerialPort port, int32_t* status) {

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -31,8 +31,19 @@ using namespace hal;
static IndexedHandleResource<HAL_SolenoidHandle, Solenoid,
kNumPCMModules * kNumSolenoidChannels,
HAL_HandleEnum::Solenoid>
solenoidHandles;
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" {
@@ -56,12 +67,12 @@ HAL_SolenoidHandle HAL_InitializeSolenoidPort(HAL_PortHandle portHandle,
return HAL_kInvalidHandle;
}
auto handle =
solenoidHandles.Allocate(module * kNumSolenoidChannels + channel, status);
auto handle = solenoidHandles->Allocate(
module * kNumSolenoidChannels + channel, status);
if (*status != 0) {
return HAL_kInvalidHandle;
}
auto solenoidPort = solenoidHandles.Get(handle);
auto solenoidPort = solenoidHandles->Get(handle);
if (solenoidPort == nullptr) { // would only occur on thread issues
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
@@ -73,7 +84,7 @@ HAL_SolenoidHandle HAL_InitializeSolenoidPort(HAL_PortHandle portHandle,
}
void HAL_FreeSolenoidPort(HAL_SolenoidHandle solenoidPortHandle) {
solenoidHandles.Free(solenoidPortHandle);
solenoidHandles->Free(solenoidPortHandle);
}
HAL_Bool HAL_CheckSolenoidModule(int32_t module) {
@@ -86,7 +97,7 @@ HAL_Bool HAL_CheckSolenoidChannel(int32_t channel) {
HAL_Bool HAL_GetSolenoid(HAL_SolenoidHandle solenoidPortHandle,
int32_t* status) {
auto port = solenoidHandles.Get(solenoidPortHandle);
auto port = solenoidHandles->Get(solenoidPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
@@ -109,7 +120,7 @@ int32_t HAL_GetAllSolenoids(int32_t module, int32_t* status) {
void HAL_SetSolenoid(HAL_SolenoidHandle solenoidPortHandle, HAL_Bool value,
int32_t* status) {
auto port = solenoidHandles.Get(solenoidPortHandle);
auto port = solenoidHandles->Get(solenoidPortHandle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
@@ -154,4 +165,25 @@ void HAL_ClearAllPCMStickyFaults(int32_t module, int32_t* status) {
*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"

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -12,6 +12,12 @@
#include "HAL/Errors.h"
namespace hal {
namespace init {
void InitializeThreads() {}
} // namespace init
} // namespace hal
extern "C" {
/**

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,6 +11,7 @@
#include <cstdio>
#include <cstring>
#include <llvm/FileSystem.h>
#include <llvm/StringRef.h>
#include "../visa/visa.h"
@@ -26,7 +27,7 @@ namespace hal {
std::string SerialHelper::m_usbNames[2]{"", ""};
std::mutex SerialHelper::m_nameMutex;
wpi::mutex SerialHelper::m_nameMutex;
SerialHelper::SerialHelper() {
viOpenDefaultRM(reinterpret_cast<ViSession*>(&m_resourceHandle));
@@ -178,9 +179,8 @@ void SerialHelper::QueryHubPaths(int32_t* status) {
// Status might be positive, so reset it to 0
*status = 0;
// Storage buffers for Visa calls and system exec calls
// Storage buffer for Visa call
char osName[256];
char execBuffer[128];
// Loop through all returned VISA objects.
// Increment the internal VISA ptr every loop
@@ -214,45 +214,30 @@ void SerialHelper::QueryHubPaths(int32_t* status) {
llvm::StringRef matchString = devNameRef.split(')').first;
if (matchString.equals(devNameRef)) continue;
// Run find using pipe to get a list of system accessors
llvm::SmallString<128> val(
"sh -c \"find /sys/devices/soc0 | grep amba | grep usb | grep ");
val += matchString;
val += "\"";
// Search directories to get a list of system accessors
std::error_code ec;
for (auto p = llvm::sys::fs::recursive_directory_iterator(
"/sys/devices/soc0", ec);
p != llvm::sys::fs::recursive_directory_iterator(); p.increment(ec)) {
if (ec) break;
llvm::StringRef path{p->path()};
if (path.find("amba") == llvm::StringRef::npos) continue;
if (path.find("usb") == llvm::StringRef::npos) continue;
if (path.find(matchString) == llvm::StringRef::npos) continue;
// Pipe code found on StackOverflow
// http://stackoverflow.com/questions/478898/how-to-execute-a-command-and-get-output-of-command-within-c-using-posix
// Using std::string because this is guarenteed to be large
std::string output = "";
std::shared_ptr<std::FILE> pipe(popen(val.c_str(), "r"), pclose);
// Just check the next item on a pipe failure
if (!pipe) continue;
while (!feof(pipe.get())) {
if (std::fgets(execBuffer, 128, pipe.get()) != 0) output += execBuffer;
}
if (!output.empty()) {
llvm::SmallVector<llvm::StringRef, 16> pathSplitVec;
// Split output by line, grab first line, and split it into
// individual directories
llvm::StringRef{output}.split('\n').first.split(pathSplitVec, '/', -1,
false);
// Split path into individual directories
path.split(pathSplitVec, '/', -1, false);
// Find each individual item index
const char* usb1 = "usb1";
const char* tty = "tty";
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 && pathSplitVec[i].equals("usb1")) {
findusb = i;
}
if (findtty == -1 && pathSplitVec[i].equals(tty)) {
if (findtty == -1 && pathSplitVec[i].equals("tty")) {
findtty = i;
}
if (findregex == -1 && pathSplitVec[i].equals(matchString)) {
@@ -274,6 +259,7 @@ void SerialHelper::QueryHubPaths(int32_t* status) {
m_visaResource.emplace_back(desc);
m_osResource.emplace_back(
llvm::StringRef{osName}.split("(").second.split(")").first);
break;
}
}
@@ -287,7 +273,7 @@ done:
int32_t SerialHelper::GetIndexForPort(HAL_SerialPort port, int32_t* status) {
// Hold lock whenever we're using the names array
std::lock_guard<std::mutex> lock(m_nameMutex);
std::lock_guard<wpi::mutex> lock(m_nameMutex);
std::string portString = m_usbNames[port - 2];

View File

@@ -1,6 +1,6 @@
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include "ctre/CtreCanNode.h"
#include "CtreCanNode.h"
#include "FRC_NetworkCommunication/CANSessionMux.h"
#include <string.h> // memset
@@ -68,17 +68,13 @@ void CtreCanNode::UnregisterTx(uint32_t arbId)
_txJobs.erase(iter);
}
}
timespec diff(const timespec & start, const timespec & end)
{
timespec temp;
if ((end.tv_nsec-start.tv_nsec)<0) {
temp.tv_sec = end.tv_sec-start.tv_sec-1;
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
} else {
temp.tv_sec = end.tv_sec-start.tv_sec;
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
}
return temp;
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)
{
@@ -90,10 +86,11 @@ CTR_Code CtreCanNode::GetRx(uint32_t arbId,uint8_t * dataBytes, uint32_t timeout
if(timeoutMs > 999)
timeoutMs = 999;
FRC_NetworkCommunication_CANSessionMux_receiveMessage(&arbId,kFullMessageIDMask,dataBytes,&len,&timeStamp,&status);
std::lock_guard<wpi::mutex> lock(_lck);
if(status == 0){
/* fresh update */
rxEvent_t & r = _rxRxEvents[arbId]; /* lookup entry or make a default new one with all zeroes */
clock_gettime(2,&r.time); /* fill in time */
r.time = GetTimeMs();
memcpy(r.bytes, dataBytes, 8); /* fill in databytes */
}else{
/* did not get the message */
@@ -107,16 +104,13 @@ CTR_Code CtreCanNode::GetRx(uint32_t arbId,uint8_t * dataBytes, uint32_t timeout
/* we've gotten this message before but not recently */
memcpy(dataBytes,i->second.bytes,8);
/* get the time now */
struct timespec temp;
clock_gettime(2,&temp); /* get now */
int64_t now = GetTimeMs(); /* get now */
/* how long has it been? */
temp = diff(i->second.time,temp); /* temp = now - last */
if(temp.tv_sec > 0){
retval = CTR_RxTimeout;
}else if(temp.tv_nsec > ((int32_t)timeoutMs*1000*1000)){
retval = CTR_RxTimeout;
}else {
/* our last update was recent enough */
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 */
}
}
}

View File

@@ -4,6 +4,7 @@
#include <map>
#include <string.h> // memcpy
#include <sys/time.h>
#include <support/mutex.h>
class CtreCanNode
{
public:
@@ -108,7 +109,7 @@ private:
class rxEvent_t{
public:
uint8_t bytes[8];
struct timespec time;
int64_t time;
rxEvent_t()
{
bytes[0] = 0;
@@ -127,5 +128,7 @@ private:
typedef std::map<uint32_t,rxEvent_t> rxRxEvents_t;
rxRxEvents_t _rxRxEvents;
wpi::mutex _lck;
};
#endif

View File

@@ -1,6 +1,6 @@
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include "ctre/PCM.h"
#include "PCM.h"
#include "FRC_NetworkCommunication/CANSessionMux.h"
#include <string.h> // memset
/* This can be a constant, as long as nobody needs to update solenoids within
@@ -213,7 +213,9 @@ CTR_Code PCM::FireOneShotSolenoid(UINT8 idx)
return CTR_OKAY;
}
/* 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.
* 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.

View File

@@ -1,4 +1,4 @@
#include "ctre/PDP.h"
#include "PDP.h"
#include "FRC_NetworkCommunication/CANSessionMux.h" //CAN Comm
#include <string.h> // memset

View File

@@ -52,6 +52,4 @@ typedef enum {
CTR_BufferFull, //!< Caller attempted to insert data into a buffer that is full.
}CTR_Code;
#include "ctre_frames.h"
#endif /* CTRE_H */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2008-2017 FIRST. All Rights Reserved. */
/* Copyright (c) 2008-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -28,6 +28,8 @@ void HAL_SetDigitalPWMOutputChannel(HAL_DigitalPWMHandle pwmGenerator,
int32_t channel, int32_t* status);
void HAL_SetDIO(HAL_DigitalHandle dioPortHandle, HAL_Bool value,
int32_t* status);
void HAL_SetDIODirection(HAL_DigitalHandle dioPortHandle, HAL_Bool input,
int32_t* status);
HAL_Bool HAL_GetDIO(HAL_DigitalHandle dioPortHandle, int32_t* status);
HAL_Bool HAL_GetDIODirection(HAL_DigitalHandle dioPortHandle, int32_t* status);
void HAL_Pulse(HAL_DigitalHandle dioPortHandle, double pulseLength,

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2013-2017 FIRST. All Rights Reserved. */
/* Copyright (c) 2013-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
@@ -47,6 +47,13 @@ enum HAL_AllianceStationID : int32_t {
HAL_AllianceStationID_kBlue3,
};
enum HAL_MatchType {
HAL_kMatchType_none,
HAL_kMatchType_practice,
HAL_kMatchType_qualification,
HAL_kMatchType_elimination,
};
/* The maximum number of axes that will be stored in a single HALJoystickAxes
* struct. This is used for allocating buffers, not bounds checking, since
* there are usually less axes in practice.
@@ -79,11 +86,18 @@ struct HAL_JoystickDescriptor {
uint8_t povCount;
};
struct HAL_MatchInfo {
char* eventName;
HAL_MatchType matchType;
uint16_t matchNumber;
uint8_t replayNumber;
char* gameSpecificMessage;
};
#ifdef __cplusplus
extern "C" {
#endif
int32_t HAL_SetErrorData(const char* errors, int32_t errorsLength,
int32_t waitMs);
int32_t HAL_SendError(HAL_Bool isError, int32_t errorCode, HAL_Bool isLVCode,
const char* details, const char* location,
const char* callStack, HAL_Bool printMsg);
@@ -105,6 +119,9 @@ int32_t HAL_SetJoystickOutputs(int32_t joystickNum, int64_t outputs,
int32_t leftRumble, int32_t rightRumble);
double HAL_GetMatchTime(int32_t* status);
int HAL_GetMatchInfo(HAL_MatchInfo* info);
void HAL_FreeMatchInfo(HAL_MatchInfo* info);
#ifndef HAL_USE_LABVIEW
void HAL_ReleaseDSMutex(void);

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2013-2017 FIRST. All Rights Reserved. */
/* Copyright (c) 2013-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
@@ -54,7 +54,7 @@ const char* HAL_GetErrorMessage(int32_t code);
int32_t HAL_GetFPGAVersion(int32_t* status);
int64_t HAL_GetFPGARevision(int32_t* status);
HAL_RuntimeType HAL_GetRuntimeType();
HAL_RuntimeType HAL_GetRuntimeType(void);
HAL_Bool HAL_GetFPGAButton(int32_t* status);
HAL_Bool HAL_GetSystemActive(int32_t* status);

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -17,10 +17,10 @@ extern "C" {
void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status);
int32_t HAL_TransactionI2C(HAL_I2CPort port, int32_t deviceAddress,
uint8_t* dataToSend, int32_t sendSize,
const uint8_t* dataToSend, int32_t sendSize,
uint8_t* dataReceived, int32_t receiveSize);
int32_t HAL_WriteI2C(HAL_I2CPort port, int32_t deviceAddress,
uint8_t* dataToSend, int32_t sendSize);
const uint8_t* dataToSend, int32_t sendSize);
int32_t HAL_ReadI2C(HAL_I2CPort port, int32_t deviceAddress, uint8_t* buffer,
int32_t count);
void HAL_CloseI2C(HAL_I2CPort port);

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -15,16 +15,16 @@
extern "C" {
#endif
typedef void (*HAL_NotifierProcessFunction)(uint64_t currentTime,
HAL_NotifierHandle handle);
HAL_NotifierHandle HAL_InitializeNotifier(HAL_NotifierProcessFunction process,
void* param, int32_t* status);
HAL_NotifierHandle HAL_InitializeNotifier(int32_t* status);
void HAL_StopNotifier(HAL_NotifierHandle notifierHandle, int32_t* status);
void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle, int32_t* status);
void* HAL_GetNotifierParam(HAL_NotifierHandle notifierHandle, int32_t* status);
void HAL_UpdateNotifierAlarm(HAL_NotifierHandle notifierHandle,
uint64_t triggerTime, int32_t* status);
void HAL_StopNotifierAlarm(HAL_NotifierHandle notifierHandle, int32_t* status);
void HAL_CancelNotifierAlarm(HAL_NotifierHandle notifierHandle,
int32_t* status);
uint64_t HAL_WaitForNotifierAlarm(HAL_NotifierHandle notifierHandle,
int32_t* status);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -9,6 +9,7 @@
#include <stdint.h>
#include "HAL/AnalogTrigger.h"
#include "HAL/Types.h"
enum HAL_SPIPort : int32_t {
@@ -24,9 +25,10 @@ extern "C" {
#endif
void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status);
int32_t HAL_TransactionSPI(HAL_SPIPort port, uint8_t* dataToSend,
int32_t HAL_TransactionSPI(HAL_SPIPort port, const uint8_t* dataToSend,
uint8_t* dataReceived, int32_t size);
int32_t HAL_WriteSPI(HAL_SPIPort port, uint8_t* dataToSend, int32_t sendSize);
int32_t HAL_WriteSPI(HAL_SPIPort port, const uint8_t* dataToSend,
int32_t sendSize);
int32_t HAL_ReadSPI(HAL_SPIPort port, uint8_t* buffer, int32_t count);
void HAL_CloseSPI(HAL_SPIPort port);
void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed);
@@ -37,23 +39,23 @@ void HAL_SetSPIChipSelectActiveLow(HAL_SPIPort port, int32_t* status);
int32_t HAL_GetSPIHandle(HAL_SPIPort port);
void HAL_SetSPIHandle(HAL_SPIPort port, int32_t handle);
void HAL_InitSPIAccumulator(HAL_SPIPort port, int32_t period, int32_t cmd,
int32_t xferSize, int32_t validMask,
int32_t validValue, int32_t dataShift,
int32_t dataSize, HAL_Bool isSigned,
HAL_Bool bigEndian, int32_t* status);
void HAL_FreeSPIAccumulator(HAL_SPIPort port, int32_t* status);
void HAL_ResetSPIAccumulator(HAL_SPIPort port, int32_t* status);
void HAL_SetSPIAccumulatorCenter(HAL_SPIPort port, int32_t center,
int32_t* status);
void HAL_SetSPIAccumulatorDeadband(HAL_SPIPort port, int32_t deadband,
int32_t* status);
int32_t HAL_GetSPIAccumulatorLastValue(HAL_SPIPort port, int32_t* status);
int64_t HAL_GetSPIAccumulatorValue(HAL_SPIPort port, int32_t* status);
int64_t HAL_GetSPIAccumulatorCount(HAL_SPIPort port, int32_t* status);
double HAL_GetSPIAccumulatorAverage(HAL_SPIPort port, int32_t* status);
void HAL_GetSPIAccumulatorOutput(HAL_SPIPort port, int64_t* value,
int64_t* count, int32_t* status);
void HAL_InitSPIAuto(HAL_SPIPort port, int32_t bufferSize, int32_t* status);
void HAL_FreeSPIAuto(HAL_SPIPort port, int32_t* status);
void HAL_StartSPIAutoRate(HAL_SPIPort port, double period, int32_t* status);
void HAL_StartSPIAutoTrigger(HAL_SPIPort port, HAL_Handle digitalSourceHandle,
HAL_AnalogTriggerType analogTriggerType,
HAL_Bool triggerRising, HAL_Bool triggerFalling,
int32_t* status);
void HAL_StopSPIAuto(HAL_SPIPort port, int32_t* status);
void HAL_SetSPIAutoTransmitData(HAL_SPIPort port, const uint8_t* dataToSend,
int32_t dataSize, int32_t zeroSize,
int32_t* status);
void HAL_ForceSPIAutoRead(HAL_SPIPort port, int32_t* status);
int32_t HAL_ReadSPIAutoReceivedData(HAL_SPIPort port, uint8_t* buffer,
int32_t numToRead, double timeout,
int32_t* status);
int32_t HAL_GetSPIAutoDroppedCount(HAL_SPIPort port, int32_t* status);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -30,6 +30,9 @@ int32_t HAL_GetPCMSolenoidBlackList(int32_t module, int32_t* status);
HAL_Bool HAL_GetPCMSolenoidVoltageStickyFault(int32_t module, int32_t* status);
HAL_Bool HAL_GetPCMSolenoidVoltageFault(int32_t module, int32_t* status);
void HAL_ClearAllPCMStickyFaults(int32_t module, int32_t* status);
void HAL_SetOneShotDuration(HAL_SolenoidHandle solenoidPortHandle,
int32_t durMS, int32_t* status);
void HAL_FireOneShot(HAL_SolenoidHandle solenoidPortHandle, int32_t* status);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -83,6 +83,14 @@ namespace nUsageReporting
kResourceType_PCM, // 60
kResourceType_PigeonIMU,
kResourceType_NidecBrushless,
kResourceType_CANifier,
kResourceType_CTRE_future0,
kResourceType_CTRE_future1,
kResourceType_CTRE_future2,
kResourceType_CTRE_future3,
kResourceType_CTRE_future4,
kResourceType_CTRE_future5,
kResourceType_CTRE_future6, // 70
} tResourceType;
typedef enum

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -52,7 +52,9 @@ inline Log::Log() {}
inline llvm::raw_ostream& Log::Get(TLogLevel level) {
oss << "- " << NowTime();
oss << " " << ToString(level) << ": ";
oss << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t');
if (level > logDEBUG) {
oss << std::string(level - logDEBUG, '\t');
}
return oss;
}
@@ -94,7 +96,7 @@ typedef Log FILELog;
if (level > FILELog::ReportingLevel()) \
; \
else \
Log().Get(level)
Log().Get(level)
inline std::string NowTime() {
llvm::SmallString<128> buf;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -9,12 +9,12 @@
#include <stdint.h>
#include <mutex>
#include <string>
#include <vector>
#include <llvm/SmallString.h>
#include <llvm/SmallVector.h>
#include <support/mutex.h>
#include "HAL/SerialPort.h"
@@ -46,7 +46,7 @@ class SerialHelper {
int32_t m_resourceHandle;
static std::mutex m_nameMutex;
static wpi::mutex m_nameMutex;
static std::string m_usbNames[2];
};
} // namespace hal

View File

@@ -0,0 +1,85 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <support/mutex.h>
#include "HAL/ChipObject.h"
#include "HAL/Types.h"
namespace hal {
struct DIOSetProxy {
DIOSetProxy(const DIOSetProxy&) = delete;
DIOSetProxy(DIOSetProxy&&) = delete;
DIOSetProxy& operator=(const DIOSetProxy&) = delete;
DIOSetProxy& operator=(DIOSetProxy&&) = delete;
void SetOutputMode(int32_t* status) {
m_dio->writeOutputEnable(m_setOutputDirReg, status);
}
void SetInputMode(int32_t* status) {
m_dio->writeOutputEnable(m_unsetOutputDirReg, status);
}
void SetOutputTrue(int32_t* status) {
m_dio->writeDO(m_setOutputStateReg, status);
}
void SetOutputFalse(int32_t* status) {
m_dio->writeDO(m_unsetOutputStateReg, status);
}
tDIO::tOutputEnable m_setOutputDirReg;
tDIO::tOutputEnable m_unsetOutputDirReg;
tDIO::tDO m_setOutputStateReg;
tDIO::tDO m_unsetOutputStateReg;
tDIO* m_dio;
};
namespace detail {
wpi::mutex& UnsafeGetDIOMutex();
tDIO* UnsafeGetDigialSystem();
int32_t ComputeDigitalMask(HAL_DigitalHandle handle, int32_t* status);
} // namespace detail
/**
* Unsafe digital output set function
* This function can be used to perform fast and determinstically set digital
* outputs. This function holds the DIO lock, so calling anyting other then
* functions on the Proxy object passed as a parameter can deadlock your
* program.
*
*/
template <typename Functor>
void UnsafeManipulateDIO(HAL_DigitalHandle handle, int32_t* status,
Functor func) {
auto port = digitalChannelHandles->Get(handle, HAL_HandleEnum::DIO);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
wpi::mutex& dioMutex = detail::UnsafeGetDIOMutex();
tDIO* dSys = detail::UnsafeGetDigialSystem();
auto mask = detail::ComputeDigitalMask(handle, status);
if (status != 0) return;
std::lock_guard<wpi::mutex> lock(dioMutex);
tDIO::tOutputEnable enableOE = dSys->readOutputEnable(status);
enableOE.value |= mask;
auto disableOE = enableOE;
disableOE.value &= ~mask;
tDIO::tDO enableDO = dSys->readDO(status);
enableDO.value |= mask;
auto disableDO = enableDO;
disableDO.value &= ~mask;
DIOSetProxy dioData{enableOE, disableOE, enableDO, disableDO, dSys};
func(dioData);
}
} // namespace hal

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,92 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
// Allows usage with std::lock_guard without including <mutex> separately
#include <mutex>
#if !defined(__linux__)
namespace hal {
// We do not want to use pthreads if in the simulator; however, in the
// simulator, we do not care about priority inversion.
typedef std::mutex priority_mutex;
typedef std::recursive_mutex priority_recursive_mutex;
} // namespace hal
#else // Covers rest of file.
#include <pthread.h>
namespace hal {
class priority_recursive_mutex {
public:
typedef pthread_mutex_t* native_handle_type;
constexpr priority_recursive_mutex() noexcept = default;
priority_recursive_mutex(const priority_recursive_mutex&) = delete;
priority_recursive_mutex& operator=(const priority_recursive_mutex&) = delete;
// Lock the mutex, blocking until it's available.
void lock();
// Unlock the mutex.
void unlock();
// Tries to lock the mutex.
bool try_lock() noexcept;
pthread_mutex_t* native_handle();
private:
// Do the equivalent of setting PTHREAD_PRIO_INHERIT and
// PTHREAD_MUTEX_RECURSIVE_NP.
#if __WORDSIZE == 64
pthread_mutex_t m_mutex = {
{0, 0, 0, 0, 0x20 | PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, {0, 0}}};
#else
pthread_mutex_t m_mutex = {
{0, 0, 0, 0x20 | PTHREAD_MUTEX_RECURSIVE_NP, 0, {0}}};
#endif
};
class priority_mutex {
public:
typedef pthread_mutex_t* native_handle_type;
constexpr priority_mutex() noexcept = default;
priority_mutex(const priority_mutex&) = delete;
priority_mutex& operator=(const priority_mutex&) = delete;
// Lock the mutex, blocking until it's available.
void lock();
// Unlock the mutex.
void unlock();
// Tries to lock the mutex.
bool try_lock() noexcept;
pthread_mutex_t* native_handle();
private:
// Do the equivalent of setting PTHREAD_PRIO_INHERIT.
#if __WORDSIZE == 64
pthread_mutex_t m_mutex = {{0, 0, 0, 0, 0x20, 0, 0, {0, 0}}};
#else
pthread_mutex_t m_mutex = {{0, 0, 0, 0x20, 0, {0}}};
#endif
};
} // namespace hal
#endif // FRC_SIMULATOR
// For backwards compatibility
#ifndef NAMESPACED_PRIORITY
using hal::priority_mutex; // NOLINT
using hal::priority_recursive_mutex; // NOLINT
#endif

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,7 +11,8 @@
#include <array>
#include <memory>
#include <mutex>
#include <support/mutex.h>
#include "HAL/Errors.h"
#include "HAL/Types.h"
@@ -48,7 +49,7 @@ class DigitalHandleResource : public HandleBase {
private:
std::array<std::shared_ptr<TStruct>, size> m_structures;
std::array<std::mutex, size> m_handleMutexes;
std::array<wpi::mutex, size> m_handleMutexes;
};
template <typename THandle, typename TStruct, int16_t size>
@@ -59,7 +60,7 @@ THandle DigitalHandleResource<THandle, TStruct, size>::Allocate(
*status = RESOURCE_OUT_OF_RANGE;
return HAL_kInvalidHandle;
}
std::lock_guard<std::mutex> sync(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
// check for allocation, otherwise allocate and return a valid handle
if (m_structures[index] != nullptr) {
*status = RESOURCE_IS_ALLOCATED;
@@ -77,7 +78,7 @@ std::shared_ptr<TStruct> DigitalHandleResource<THandle, TStruct, size>::Get(
if (index < 0 || index >= size) {
return nullptr;
}
std::lock_guard<std::mutex> sync(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
// return structure. Null will propogate correctly, so no need to manually
// check.
return m_structures[index];
@@ -90,14 +91,14 @@ void DigitalHandleResource<THandle, TStruct, size>::Free(
int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
if (index < 0 || index >= size) return;
// lock and deallocated handle
std::lock_guard<std::mutex> sync(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
m_structures[index].reset();
}
template <typename THandle, typename TStruct, int16_t size>
void DigitalHandleResource<THandle, TStruct, size>::ResetHandles() {
for (int i = 0; i < size; i++) {
std::lock_guard<std::mutex> sync(m_handleMutexes[i]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[i]);
m_structures[i].reset();
}
HandleBase::ResetHandles();

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -77,7 +77,7 @@ static inline int16_t getHandleTypedIndex(HAL_Handle handle,
HAL_HandleEnum enumType,
int16_t version) {
if (!isHandleType(handle, enumType)) return InvalidHandleIndex;
#if !defined(CONFIG_ATHENA)
#if !defined(__FRC_ROBORIO__)
if (!isHandleCorrectVersion(handle, version)) return InvalidHandleIndex;
#endif
return getHandleIndex(handle);

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -9,13 +9,15 @@
#include <stdint.h>
#include <array>
#include <memory>
#include <vector>
#include <support/mutex.h>
#include "HAL/Errors.h"
#include "HAL/Types.h"
#include "HAL/cpp/make_unique.h"
#include "HAL/cpp/priority_mutex.h"
#include "HAL/handles/HandlesInternal.h"
namespace hal {
@@ -39,7 +41,7 @@ class IndexedClassedHandleResource : public HandleBase {
friend class IndexedClassedHandleResourceTest;
public:
IndexedClassedHandleResource();
IndexedClassedHandleResource() = default;
IndexedClassedHandleResource(const IndexedClassedHandleResource&) = delete;
IndexedClassedHandleResource& operator=(const IndexedClassedHandleResource&) =
delete;
@@ -48,20 +50,13 @@ class IndexedClassedHandleResource : public HandleBase {
int32_t* status);
std::shared_ptr<TStruct> Get(THandle handle);
void Free(THandle handle);
void ResetHandles();
private:
std::array<std::shared_ptr<TStruct>[], size> m_structures;
std::array<std::mutex[], size> m_handleMutexes;
std::array<std::shared_ptr<TStruct>, size> m_structures;
std::array<wpi::mutex, size> m_handleMutexes;
};
template <typename THandle, typename TStruct, int16_t size,
HAL_HandleEnum enumValue>
IndexedClassedHandleResource<THandle, TStruct, size,
enumValue>::IndexedClassedHandleResource() {
m_structures = std::make_unique<std::shared_ptr<TStruct>[]>(size);
m_handleMutexes = std::make_unique<std::mutex[]>(size);
}
template <typename THandle, typename TStruct, int16_t size,
HAL_HandleEnum enumValue>
THandle
@@ -72,7 +67,7 @@ IndexedClassedHandleResource<THandle, TStruct, size, enumValue>::Allocate(
*status = RESOURCE_OUT_OF_RANGE;
return HAL_kInvalidHandle;
}
std::lock_guard<std::mutex> sync(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
// check for allocation, otherwise allocate and return a valid handle
if (m_structures[index] != nullptr) {
*status = RESOURCE_IS_ALLOCATED;
@@ -84,14 +79,15 @@ IndexedClassedHandleResource<THandle, TStruct, size, enumValue>::Allocate(
template <typename THandle, typename TStruct, int16_t size,
HAL_HandleEnum enumValue>
std::shared_ptr<TStruct> IndexedClassedHandleResource<
THandle, TStruct, size, enumValue>::Get(THandle handle) {
std::shared_ptr<TStruct>
IndexedClassedHandleResource<THandle, TStruct, size, enumValue>::Get(
THandle handle) {
// get handle index, and fail early if index out of range or wrong handle
int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
if (index < 0 || index >= size) {
return nullptr;
}
std::lock_guard<std::mutex> sync(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
// return structure. Null will propogate correctly, so no need to manually
// check.
return m_structures[index];
@@ -105,7 +101,7 @@ void IndexedClassedHandleResource<THandle, TStruct, size, enumValue>::Free(
int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
if (index < 0 || index >= size) return;
// lock and deallocated handle
std::lock_guard<std::mutex> sync(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
m_structures[index].reset();
}
@@ -114,7 +110,7 @@ template <typename THandle, typename TStruct, int16_t size,
void IndexedClassedHandleResource<THandle, TStruct, size,
enumValue>::ResetHandles() {
for (int i = 0; i < size; i++) {
std::lock_guard<std::mutex> sync(m_handleMutexes[i]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[i]);
m_structures[i].reset();
}
HandleBase::ResetHandles();

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,7 +11,8 @@
#include <array>
#include <memory>
#include <mutex>
#include <support/mutex.h>
#include "HAL/Errors.h"
#include "HAL/Types.h"
@@ -49,7 +50,7 @@ class IndexedHandleResource : public HandleBase {
private:
std::array<std::shared_ptr<TStruct>, size> m_structures;
std::array<std::mutex, size> m_handleMutexes;
std::array<wpi::mutex, size> m_handleMutexes;
};
template <typename THandle, typename TStruct, int16_t size,
@@ -61,7 +62,7 @@ THandle IndexedHandleResource<THandle, TStruct, size, enumValue>::Allocate(
*status = RESOURCE_OUT_OF_RANGE;
return HAL_kInvalidHandle;
}
std::lock_guard<std::mutex> sync(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
// check for allocation, otherwise allocate and return a valid handle
if (m_structures[index] != nullptr) {
*status = RESOURCE_IS_ALLOCATED;
@@ -80,7 +81,7 @@ IndexedHandleResource<THandle, TStruct, size, enumValue>::Get(THandle handle) {
if (index < 0 || index >= size) {
return nullptr;
}
std::lock_guard<std::mutex> sync(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
// return structure. Null will propogate correctly, so no need to manually
// check.
return m_structures[index];
@@ -94,7 +95,7 @@ void IndexedHandleResource<THandle, TStruct, size, enumValue>::Free(
int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
if (index < 0 || index >= size) return;
// lock and deallocated handle
std::lock_guard<std::mutex> sync(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
m_structures[index].reset();
}
@@ -102,7 +103,7 @@ template <typename THandle, typename TStruct, int16_t size,
HAL_HandleEnum enumValue>
void IndexedHandleResource<THandle, TStruct, size, enumValue>::ResetHandles() {
for (int i = 0; i < size; i++) {
std::lock_guard<std::mutex> sync(m_handleMutexes[i]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[i]);
m_structures[i].reset();
}
HandleBase::ResetHandles();

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,7 +11,8 @@
#include <array>
#include <memory>
#include <mutex>
#include <support/mutex.h>
#include "HAL/Types.h"
#include "HAL/cpp/make_unique.h"
@@ -48,8 +49,8 @@ class LimitedClassedHandleResource : public HandleBase {
private:
std::array<std::shared_ptr<TStruct>, size> m_structures;
std::array<std::mutex, size> m_handleMutexes;
std::mutex m_allocateMutex;
std::array<wpi::mutex, size> m_handleMutexes;
wpi::mutex m_allocateMutex;
};
template <typename THandle, typename TStruct, int16_t size,
@@ -58,12 +59,12 @@ THandle
LimitedClassedHandleResource<THandle, TStruct, size, enumValue>::Allocate(
std::shared_ptr<TStruct> toSet) {
// globally lock to loop through indices
std::lock_guard<std::mutex> sync(m_allocateMutex);
std::lock_guard<wpi::mutex> lock(m_allocateMutex);
for (int16_t i = 0; i < size; i++) {
if (m_structures[i] == nullptr) {
// if a false index is found, grab its specific mutex
// and allocate it.
std::lock_guard<std::mutex> sync(m_handleMutexes[i]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[i]);
m_structures[i] = toSet;
return static_cast<THandle>(createHandle(i, enumValue, m_version));
}
@@ -73,14 +74,15 @@ LimitedClassedHandleResource<THandle, TStruct, size, enumValue>::Allocate(
template <typename THandle, typename TStruct, int16_t size,
HAL_HandleEnum enumValue>
std::shared_ptr<TStruct> LimitedClassedHandleResource<
THandle, TStruct, size, enumValue>::Get(THandle handle) {
std::shared_ptr<TStruct>
LimitedClassedHandleResource<THandle, TStruct, size, enumValue>::Get(
THandle handle) {
// get handle index, and fail early if index out of range or wrong handle
int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
if (index < 0 || index >= size) {
return nullptr;
}
std::lock_guard<std::mutex> sync(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
// return structure. Null will propogate correctly, so no need to manually
// check.
return m_structures[index];
@@ -94,8 +96,8 @@ void LimitedClassedHandleResource<THandle, TStruct, size, enumValue>::Free(
int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
if (index < 0 || index >= size) return;
// lock and deallocated handle
std::lock_guard<std::mutex> sync(m_allocateMutex);
std::lock_guard<std::mutex> lock(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> allocateLock(m_allocateMutex);
std::lock_guard<wpi::mutex> handleLock(m_handleMutexes[index]);
m_structures[index].reset();
}
@@ -104,9 +106,9 @@ template <typename THandle, typename TStruct, int16_t size,
void LimitedClassedHandleResource<THandle, TStruct, size,
enumValue>::ResetHandles() {
{
std::lock_guard<std::mutex> lock(m_allocateMutex);
std::lock_guard<wpi::mutex> allocateLock(m_allocateMutex);
for (int i = 0; i < size; i++) {
std::lock_guard<std::mutex> sync(m_handleMutexes[i]);
std::lock_guard<wpi::mutex> handleLock(m_handleMutexes[i]);
m_structures[i].reset();
}
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2017 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,7 +11,8 @@
#include <array>
#include <memory>
#include <mutex>
#include <support/mutex.h>
#include "HAL/Types.h"
#include "HAL/cpp/make_unique.h"
@@ -46,20 +47,20 @@ class LimitedHandleResource : public HandleBase {
private:
std::array<std::shared_ptr<TStruct>, size> m_structures;
std::array<std::mutex, size> m_handleMutexes;
std::mutex m_allocateMutex;
std::array<wpi::mutex, size> m_handleMutexes;
wpi::mutex m_allocateMutex;
};
template <typename THandle, typename TStruct, int16_t size,
HAL_HandleEnum enumValue>
THandle LimitedHandleResource<THandle, TStruct, size, enumValue>::Allocate() {
// globally lock to loop through indices
std::lock_guard<std::mutex> sync(m_allocateMutex);
std::lock_guard<wpi::mutex> lock(m_allocateMutex);
for (int16_t i = 0; i < size; i++) {
if (m_structures[i] == nullptr) {
// if a false index is found, grab its specific mutex
// and allocate it.
std::lock_guard<std::mutex> sync(m_handleMutexes[i]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[i]);
m_structures[i] = std::make_shared<TStruct>();
return static_cast<THandle>(createHandle(i, enumValue, m_version));
}
@@ -76,7 +77,7 @@ LimitedHandleResource<THandle, TStruct, size, enumValue>::Get(THandle handle) {
if (index < 0 || index >= size) {
return nullptr;
}
std::lock_guard<std::mutex> sync(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
// return structure. Null will propogate correctly, so no need to manually
// check.
return m_structures[index];
@@ -90,8 +91,8 @@ void LimitedHandleResource<THandle, TStruct, size, enumValue>::Free(
int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
if (index < 0 || index >= size) return;
// lock and deallocated handle
std::lock_guard<std::mutex> sync(m_allocateMutex);
std::lock_guard<std::mutex> lock(m_handleMutexes[index]);
std::lock_guard<wpi::mutex> allocateLock(m_allocateMutex);
std::lock_guard<wpi::mutex> handleLock(m_handleMutexes[index]);
m_structures[index].reset();
}
@@ -99,9 +100,9 @@ template <typename THandle, typename TStruct, int16_t size,
HAL_HandleEnum enumValue>
void LimitedHandleResource<THandle, TStruct, size, enumValue>::ResetHandles() {
{
std::lock_guard<std::mutex> lock(m_allocateMutex);
std::lock_guard<wpi::mutex> allocateLock(m_allocateMutex);
for (int i = 0; i < size; i++) {
std::lock_guard<std::mutex> sync(m_handleMutexes[i]);
std::lock_guard<wpi::mutex> handleLock(m_handleMutexes[i]);
m_structures[i].reset();
}
}

Some files were not shown because too many files have changed in this diff Show More