diff --git a/wpilibc/src/main/native/cpp/DriverStation.cpp b/wpilibc/src/main/native/cpp/DriverStation.cpp index 98a7fa6e64..b680584356 100644 --- a/wpilibc/src/main/native/cpp/DriverStation.cpp +++ b/wpilibc/src/main/native/cpp/DriverStation.cpp @@ -20,6 +20,16 @@ #include "Utility.h" #include "WPIErrors.h" +namespace frc { +struct MatchInfoData { + std::string eventName; + std::string gameSpecificMessage; + int matchNumber = 0; + int replayNumber = 0; + DriverStation::MatchType matchType = DriverStation::MatchType::kNone; +}; +} // namespace frc + using namespace frc; const double JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL = 1.0; @@ -93,7 +103,7 @@ bool DriverStation::GetStickButton(int stick, int button) { "ERROR: Button indexes begin at 1 in WPILib for C++ and Java"); return false; } - std::unique_lock lock(m_joystickDataMutex); + std::unique_lock lock(m_cacheDataMutex); if (button > m_joystickButtons[stick].count) { // Unlock early so error printing isn't locked. lock.unlock(); @@ -124,7 +134,7 @@ bool DriverStation::GetStickButtonPressed(int stick, int button) { "ERROR: Button indexes begin at 1 in WPILib for C++ and Java"); return false; } - std::unique_lock lock(m_joystickDataMutex); + std::unique_lock lock(m_cacheDataMutex); if (button > m_joystickButtons[stick].count) { // Unlock early so error printing isn't locked. lock.unlock(); @@ -161,7 +171,7 @@ bool DriverStation::GetStickButtonReleased(int stick, int button) { "ERROR: Button indexes begin at 1 in WPILib for C++ and Java"); return false; } - std::unique_lock lock(m_joystickDataMutex); + std::unique_lock lock(m_cacheDataMutex); if (button > m_joystickButtons[stick].count) { // Unlock early so error printing isn't locked. lock.unlock(); @@ -194,10 +204,10 @@ double DriverStation::GetStickAxis(int stick, int axis) { wpi_setWPIError(BadJoystickIndex); return 0; } - std::unique_lock lock(m_joystickDataMutex); + std::unique_lock lock(m_cacheDataMutex); if (axis >= m_joystickAxes[stick].count) { // Unlock early so error printing isn't locked. - m_joystickDataMutex.unlock(); + m_cacheDataMutex.unlock(); lock.release(); if (axis >= HAL_kMaxJoystickAxes) wpi_setWPIError(BadJoystickAxis); @@ -220,7 +230,7 @@ int DriverStation::GetStickPOV(int stick, int pov) { wpi_setWPIError(BadJoystickIndex); return -1; } - std::unique_lock lock(m_joystickDataMutex); + std::unique_lock lock(m_cacheDataMutex); if (pov >= m_joystickPOVs[stick].count) { // Unlock early so error printing isn't locked. lock.unlock(); @@ -246,7 +256,7 @@ int DriverStation::GetStickButtons(int stick) const { wpi_setWPIError(BadJoystickIndex); return 0; } - std::lock_guard lock(m_joystickDataMutex); + std::lock_guard lock(m_cacheDataMutex); return m_joystickButtons[stick].buttons; } @@ -261,7 +271,7 @@ int DriverStation::GetStickAxisCount(int stick) const { wpi_setWPIError(BadJoystickIndex); return 0; } - std::lock_guard lock(m_joystickDataMutex); + std::lock_guard lock(m_cacheDataMutex); return m_joystickAxes[stick].count; } @@ -276,7 +286,7 @@ int DriverStation::GetStickPOVCount(int stick) const { wpi_setWPIError(BadJoystickIndex); return 0; } - std::lock_guard lock(m_joystickDataMutex); + std::lock_guard lock(m_cacheDataMutex); return m_joystickPOVs[stick].count; } @@ -291,7 +301,7 @@ int DriverStation::GetStickButtonCount(int stick) const { wpi_setWPIError(BadJoystickIndex); return 0; } - std::lock_guard lock(m_joystickDataMutex); + std::lock_guard lock(m_cacheDataMutex); return m_joystickButtons[stick].count; } @@ -306,7 +316,7 @@ bool DriverStation::GetJoystickIsXbox(int stick) const { wpi_setWPIError(BadJoystickIndex); return false; } - std::lock_guard lock(m_joystickDataMutex); + std::lock_guard lock(m_cacheDataMutex); return static_cast(m_joystickDescriptor[stick].isXbox); } @@ -321,7 +331,7 @@ int DriverStation::GetJoystickType(int stick) const { wpi_setWPIError(BadJoystickIndex); return -1; } - std::lock_guard lock(m_joystickDataMutex); + std::lock_guard lock(m_cacheDataMutex); return static_cast(m_joystickDescriptor[stick].type); } @@ -335,7 +345,7 @@ std::string DriverStation::GetJoystickName(int stick) const { if (stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); } - std::lock_guard lock(m_joystickDataMutex); + std::lock_guard lock(m_cacheDataMutex); std::string retVal(m_joystickDescriptor[stick].name); return retVal; } @@ -351,7 +361,7 @@ int DriverStation::GetJoystickAxisType(int stick, int axis) const { wpi_setWPIError(BadJoystickIndex); return -1; } - std::lock_guard lock(m_joystickDataMutex); + std::lock_guard lock(m_cacheDataMutex); return m_joystickDescriptor[stick].axisTypes[axis]; } @@ -471,6 +481,31 @@ bool DriverStation::IsBrownedOut() const { return retVal; } +std::string DriverStation::GetGameSpecificMessage() const { + std::lock_guard lock(m_cacheDataMutex); + return m_matchInfo->gameSpecificMessage; +} + +std::string DriverStation::GetEventName() const { + std::lock_guard lock(m_cacheDataMutex); + return m_matchInfo->eventName; +} + +DriverStation::MatchType DriverStation::GetMatchType() const { + std::lock_guard lock(m_cacheDataMutex); + return m_matchInfo->matchType; +} + +int DriverStation::GetMatchNumber() const { + std::lock_guard lock(m_cacheDataMutex); + return m_matchInfo->matchNumber; +} + +int DriverStation::GetReplayNumber() const { + std::lock_guard lock(m_cacheDataMutex); + return m_matchInfo->replayNumber; +} + /** * Return the alliance that the driver station says it is on. * @@ -597,12 +632,25 @@ void DriverStation::GetData() { HAL_GetJoystickButtons(stick, &m_joystickButtonsCache[stick]); HAL_GetJoystickDescriptor(stick, &m_joystickDescriptorCache[stick]); } + // Grab match specific data + HAL_MatchInfo matchInfo; + auto status = HAL_GetMatchInfo(&matchInfo); + if (status == 0) { + m_matchInfoCache->eventName = matchInfo.eventName; + m_matchInfoCache->matchNumber = matchInfo.matchNumber; + m_matchInfoCache->replayNumber = matchInfo.replayNumber; + m_matchInfoCache->matchType = + static_cast(matchInfo.matchType); + m_matchInfoCache->gameSpecificMessage = matchInfo.gameSpecificMessage; + } + HAL_FreeMatchInfo(&matchInfo); + // Force a control word update, to make sure the data is the newest. HAL_ControlWord controlWord; UpdateControlWord(true, controlWord); // Obtain a write lock on the data, swap the cached data into the // main data arrays - std::lock_guard lock(m_joystickDataMutex); + std::lock_guard lock(m_cacheDataMutex); for (int32_t i = 0; i < kJoystickPorts; i++) { // If buttons weren't pressed and are now, set flags in m_buttonsPressed @@ -618,6 +666,7 @@ void DriverStation::GetData() { m_joystickPOVs.swap(m_joystickPOVsCache); m_joystickButtons.swap(m_joystickButtonsCache); m_joystickDescriptor.swap(m_joystickDescriptorCache); + m_matchInfo.swap(m_matchInfoCache); } /** @@ -631,12 +680,14 @@ DriverStation::DriverStation() { m_joystickButtons = std::make_unique(kJoystickPorts); m_joystickDescriptor = std::make_unique(kJoystickPorts); + m_matchInfo = std::make_unique(); m_joystickAxesCache = std::make_unique(kJoystickPorts); m_joystickPOVsCache = std::make_unique(kJoystickPorts); m_joystickButtonsCache = std::make_unique(kJoystickPorts); m_joystickDescriptorCache = std::make_unique(kJoystickPorts); + m_matchInfoCache = std::make_unique(); // All joysticks should default to having zero axes, povs and buttons, so // uninitialized memory doesn't get sent to speed controllers. diff --git a/wpilibc/src/main/native/include/DriverStation.h b/wpilibc/src/main/native/include/DriverStation.h index 7355a0a15c..cdc565a524 100644 --- a/wpilibc/src/main/native/include/DriverStation.h +++ b/wpilibc/src/main/native/include/DriverStation.h @@ -22,6 +22,8 @@ namespace frc { +struct MatchInfoData; + /** * Provide access to the network communication data to / from the Driver * Station. @@ -29,6 +31,7 @@ namespace frc { class DriverStation : public SensorBase, public RobotStateInterface { public: enum Alliance { kRed, kBlue, kInvalid }; + enum MatchType { kNone, kPractice, kQualification, kElimination }; virtual ~DriverStation(); static DriverStation& GetInstance(); @@ -67,6 +70,12 @@ class DriverStation : public SensorBase, public RobotStateInterface { bool IsSysActive() const; bool IsBrownedOut() const; + std::string GetGameSpecificMessage() const; + std::string GetEventName() const; + MatchType GetMatchType() const; + int GetMatchNumber() const; + int GetReplayNumber() const; + Alliance GetAlliance() const; int GetLocation() const; void WaitForData(); @@ -109,12 +118,14 @@ class DriverStation : public SensorBase, public RobotStateInterface { std::unique_ptr m_joystickPOVs; std::unique_ptr m_joystickButtons; std::unique_ptr m_joystickDescriptor; + std::unique_ptr m_matchInfo; // Joystick Cached Data std::unique_ptr m_joystickAxesCache; std::unique_ptr m_joystickPOVsCache; std::unique_ptr m_joystickButtonsCache; std::unique_ptr m_joystickDescriptorCache; + std::unique_ptr m_matchInfoCache; // Joystick button rising/falling edge flags std::array m_joystickButtonsPressed; @@ -124,7 +135,7 @@ class DriverStation : public SensorBase, public RobotStateInterface { std::thread m_dsThread; std::atomic m_isRunning{false}; - mutable std::mutex m_joystickDataMutex; + mutable std::mutex m_cacheDataMutex; // Robot state status variables bool m_userInDisabled = false; diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DriverStation.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DriverStation.java index 6425be4395..784b7d6f70 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DriverStation.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DriverStation.java @@ -12,6 +12,7 @@ import java.nio.ByteBuffer; import edu.wpi.first.wpilibj.hal.AllianceStationID; import edu.wpi.first.wpilibj.hal.ControlWord; import edu.wpi.first.wpilibj.hal.HAL; +import edu.wpi.first.wpilibj.hal.MatchInfoData; import edu.wpi.first.wpilibj.hal.PowerJNI; /** @@ -54,6 +55,10 @@ public class DriverStation implements RobotState.Interface { Red, Blue, Invalid } + public enum MatchType { + None, Practice, Qualification, Elimination + } + private static final double JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL = 1.0; private double m_nextMessageTime = 0.0; @@ -76,11 +81,13 @@ public class DriverStation implements RobotState.Interface { private HALJoystickAxes[] m_joystickAxes = new HALJoystickAxes[kJoystickPorts]; private HALJoystickPOVs[] m_joystickPOVs = new HALJoystickPOVs[kJoystickPorts]; private HALJoystickButtons[] m_joystickButtons = new HALJoystickButtons[kJoystickPorts]; + private MatchInfoData m_matchInfo = new MatchInfoData(); // Joystick Cached Data private HALJoystickAxes[] m_joystickAxesCache = new HALJoystickAxes[kJoystickPorts]; private HALJoystickPOVs[] m_joystickPOVsCache = new HALJoystickPOVs[kJoystickPorts]; private HALJoystickButtons[] m_joystickButtonsCache = new HALJoystickButtons[kJoystickPorts]; + private MatchInfoData m_matchInfoCache = new MatchInfoData(); // Joystick button rising/falling edge flags HALJoystickButtons[] m_joystickButtonsPressed = new HALJoystickButtons[kJoystickPorts]; @@ -93,7 +100,7 @@ public class DriverStation implements RobotState.Interface { private Thread m_thread; private volatile boolean m_threadKeepAlive = true; - private final Object m_joystickMutex; + private final Object m_cacheDataMutex; // Robot state status variables private boolean m_userInDisabled = false; @@ -122,7 +129,7 @@ public class DriverStation implements RobotState.Interface { * variable. */ private DriverStation() { - m_joystickMutex = new Object(); + m_cacheDataMutex = new Object(); for (int i = 0; i < kJoystickPorts; i++) { m_joystickButtons[i] = new HALJoystickButtons(); m_joystickAxes[i] = new HALJoystickAxes(HAL.kMaxJoystickAxes); @@ -244,7 +251,7 @@ public class DriverStation implements RobotState.Interface { } boolean error = false; boolean retVal = false; - synchronized (m_joystickMutex) { + synchronized (m_cacheDataMutex) { if (button > m_joystickButtons[stick].m_count) { error = true; retVal = false; @@ -328,7 +335,7 @@ public class DriverStation implements RobotState.Interface { boolean error = false; double retVal = 0.0; - synchronized (m_joystickMutex) { + synchronized (m_cacheDataMutex) { if (axis >= m_joystickAxes[stick].m_count) { // set error error = true; @@ -358,7 +365,7 @@ public class DriverStation implements RobotState.Interface { } boolean error = false; int retVal = -1; - synchronized (m_joystickMutex) { + synchronized (m_cacheDataMutex) { if (pov >= m_joystickPOVs[stick].m_count) { error = true; retVal = -1; @@ -383,7 +390,7 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-3"); } - synchronized (m_joystickMutex) { + synchronized (m_cacheDataMutex) { return m_joystickButtons[stick].m_buttons; } } @@ -398,7 +405,7 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-5"); } - synchronized (m_joystickMutex) { + synchronized (m_cacheDataMutex) { return m_joystickAxes[stick].m_count; } } @@ -413,7 +420,7 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-5"); } - synchronized (m_joystickMutex) { + synchronized (m_cacheDataMutex) { return m_joystickPOVs[stick].m_count; } } @@ -428,7 +435,7 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-5"); } - synchronized (m_joystickMutex) { + synchronized (m_cacheDataMutex) { return m_joystickButtons[stick].m_count; } } @@ -445,7 +452,7 @@ public class DriverStation implements RobotState.Interface { } boolean error = false; boolean retVal = false; - synchronized (m_joystickMutex) { + synchronized (m_cacheDataMutex) { // TODO: Remove this when calling for descriptor on empty stick no longer // crashes if (1 > m_joystickButtons[stick].m_count && 1 > m_joystickAxes[stick].m_count) { @@ -474,7 +481,7 @@ public class DriverStation implements RobotState.Interface { } boolean error = false; int retVal = -1; - synchronized (m_joystickMutex) { + synchronized (m_cacheDataMutex) { // TODO: Remove this when calling for descriptor on empty stick no longer // crashes if (1 > m_joystickButtons[stick].m_count && 1 > m_joystickAxes[stick].m_count) { @@ -503,7 +510,7 @@ public class DriverStation implements RobotState.Interface { } boolean error = false; String retVal = ""; - synchronized (m_joystickMutex) { + synchronized (m_cacheDataMutex) { // TODO: Remove this when calling for descriptor on empty stick no longer // crashes if (1 > m_joystickButtons[stick].m_count && 1 > m_joystickAxes[stick].m_count) { @@ -533,7 +540,7 @@ public class DriverStation implements RobotState.Interface { } int retVal = -1; - synchronized (m_joystickMutex) { + synchronized (m_cacheDataMutex) { retVal = HAL.getJoystickAxisType((byte) stick, (byte) axis); } return retVal; @@ -649,6 +656,72 @@ public class DriverStation implements RobotState.Interface { return HAL.getBrownedOut(); } + /** + * Get the game specific message. + * + * @return the game specific message + */ + public String getGameSpecificMessage() { + synchronized (m_cacheDataMutex) { + return m_matchInfo.gameSpecificMessage; + } + } + + /** + * Get the event name. + * + * @return the event name + */ + public String getEventName() { + synchronized (m_cacheDataMutex) { + return m_matchInfo.eventName; + } + } + + /** + * Get the match type. + * + * @return the match type + */ + public MatchType getMatchType() { + int matchType; + synchronized (m_cacheDataMutex) { + matchType = m_matchInfo.matchType; + } + switch (matchType) { + case 1: + return MatchType.Practice; + case 2: + return MatchType.Qualification; + case 3: + return MatchType.Elimination; + default: + return MatchType.None; + } + } + + /** + * Get the match number. + * + * @return the match number + */ + public int getMatchNumber() { + synchronized (m_cacheDataMutex) { + return m_matchInfo.matchNumber; + } + } + + /** + * Get the replay number. + * + * @return the replay number + */ + public int getReplayNumber() { + synchronized (m_cacheDataMutex) { + return m_matchInfo.replayNumber; + } + } + /** * Get the current alliance from the FMS. * @@ -802,11 +875,14 @@ public class DriverStation implements RobotState.Interface { m_joystickButtonsCache[stick].m_buttons = HAL.getJoystickButtons(stick, m_buttonCountBuffer); m_joystickButtonsCache[stick].m_count = m_buttonCountBuffer.get(0); } + + HAL.getMatchInfo(m_matchInfoCache); + // Force a control word update, to make sure the data is the newest. updateControlWord(true); // lock joystick mutex to swap cache data - synchronized (m_joystickMutex) { + synchronized (m_cacheDataMutex) { for (int i = 0; i < kJoystickPorts; i++) { // If buttons weren't pressed and are now, set flags in m_buttonsPressed m_joystickButtonsPressed[i].m_buttons |= @@ -829,6 +905,10 @@ public class DriverStation implements RobotState.Interface { HALJoystickPOVs[] currentPOVs = m_joystickPOVs; m_joystickPOVs = m_joystickPOVsCache; m_joystickPOVsCache = currentPOVs; + + MatchInfoData currentInfo = m_matchInfo; + m_matchInfo = m_matchInfoCache; + m_matchInfoCache = currentInfo; } } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/hal/HAL.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/hal/HAL.java index 5e1dd540a5..aa668dab63 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/hal/HAL.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/hal/HAL.java @@ -118,6 +118,8 @@ public class HAL extends JNIWrapper { public static native boolean getBrownedOut(); + public static native int getMatchInfo(MatchInfoData info); + public static native int setErrorData(String error); public static native int sendError(boolean isError, int errorCode, boolean isLVCode, diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/hal/MatchInfoData.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/hal/MatchInfoData.java new file mode 100644 index 0000000000..bd164c9b7f --- /dev/null +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/hal/MatchInfoData.java @@ -0,0 +1,56 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 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. */ +/*----------------------------------------------------------------------------*/ + +package edu.wpi.first.wpilibj.hal; + +/** + * Structure for holding the match info data request. + */ +public class MatchInfoData { + /** + * Stores the event name. + */ + @SuppressWarnings("MemberName") + public String eventName; + + /** + * Stores the game specific message. + */ + @SuppressWarnings("MemberName") + public String gameSpecificMessage; + + /** + * Stores the match number. + */ + @SuppressWarnings("MemberName") + public int matchNumber; + + /** + * Stores the replay number. + */ + @SuppressWarnings("MemberName") + public int replayNumber; + + /** + * Stores the match type. + */ + @SuppressWarnings("MemberName") + public int matchType; + + /** + * Called from JNI to set the structure data. + */ + @SuppressWarnings("JavadocMethod") + public void setData(String eventName, String gameSpecificMessage, + int matchNumber, int replayNumber, int matchType) { + this.eventName = eventName; + this.gameSpecificMessage = gameSpecificMessage; + this.matchNumber = matchNumber; + this.replayNumber = replayNumber; + this.matchType = matchType; + } +} diff --git a/wpilibj/src/main/native/cpp/HAL.cpp b/wpilibj/src/main/native/cpp/HAL.cpp index d60aad6c21..6634e9ee3c 100644 --- a/wpilibj/src/main/native/cpp/HAL.cpp +++ b/wpilibj/src/main/native/cpp/HAL.cpp @@ -120,7 +120,7 @@ Java_edu_wpi_first_wpilibj_hal_HAL_report( JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_HAL_nativeGetControlWord(JNIEnv*, jclass) { NETCOMM_LOG(logDEBUG) << "Calling HAL Control Word"; - static_assert(sizeof(HAL_ControlWord) == sizeof(jint), + static_assert(sizeof(HAL_ControlWord) == sizeof(jint), "Java int must match the size of control word"); HAL_ControlWord controlWord; std::memset(&controlWord, 0, sizeof(HAL_ControlWord)); @@ -285,7 +285,7 @@ Java_edu_wpi_first_wpilibj_hal_HAL_getJoystickAxisType(JNIEnv*, jclass, * Method: isNewControlData * Signature: ()Z */ -JNIEXPORT jboolean JNICALL +JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_hal_HAL_isNewControlData(JNIEnv *, jclass) { return static_cast(HAL_IsNewControlData()); } @@ -315,8 +315,8 @@ Java_edu_wpi_first_wpilibj_hal_HAL_releaseDSMutex(JNIEnv* env, jclass) { * Method: waitForDSDataTimeout * Signature: (D)Z */ -JNIEXPORT jboolean JNICALL -Java_edu_wpi_first_wpilibj_hal_HAL_waitForDSDataTimeout(JNIEnv *, jclass, +JNIEXPORT jboolean JNICALL +Java_edu_wpi_first_wpilibj_hal_HAL_waitForDSDataTimeout(JNIEnv *, jclass, jdouble timeout) { return static_cast(HAL_WaitForDSDataTimeout(timeout)); } @@ -358,6 +358,23 @@ Java_edu_wpi_first_wpilibj_hal_HAL_getBrownedOut(JNIEnv* env, jclass) { return val; } +/* + * Class: edu_wpi_first_wpilibj_hal_HAL + * Method: getMatchInfo + * Signature: (Ledu/wpi/first/wpilibj/hal/MatchInfoData;)I + */ +JNIEXPORT jint JNICALL +Java_edu_wpi_first_wpilibj_hal_HAL_getMatchInfo +(JNIEnv * env, jclass, jobject info) { + HAL_MatchInfo matchInfo; + auto status = HAL_GetMatchInfo(&matchInfo); + if (status == 0) { + SetMatchInfoObject(env, info, matchInfo); + } + HAL_FreeMatchInfo(&matchInfo); + return status; +} + /* * Class: edu_wpi_first_wpilibj_hal_HAL * Method: HAL_SendError diff --git a/wpilibj/src/main/native/cpp/HALUtil.cpp b/wpilibj/src/main/native/cpp/HALUtil.cpp index d5192d7491..6fcf95f306 100644 --- a/wpilibj/src/main/native/cpp/HALUtil.cpp +++ b/wpilibj/src/main/native/cpp/HALUtil.cpp @@ -56,6 +56,7 @@ static JException canNotInitializedExCls; static JException uncleanStatusExCls; static JClass pwmConfigDataResultCls; static JClass canStatusCls; +static JClass matchInfoDataCls; namespace frc { @@ -208,17 +209,30 @@ jobject CreatePWMConfigDataResult(JNIEnv *env, int32_t maxPwm, minPwm); } -void SetCanStatusObject(JNIEnv *env, jobject canStatus, +void SetCanStatusObject(JNIEnv *env, jobject canStatus, float percentBusUtilization, - uint32_t busOffCount, uint32_t txFullCount, - uint32_t receiveErrorCount, + uint32_t busOffCount, uint32_t txFullCount, + uint32_t receiveErrorCount, uint32_t transmitErrorCount) { - static jmethodID func = env->GetMethodID(canStatusCls, "setStatus", - "(DIIII)V"); - env->CallObjectMethod(canStatus, func, (jdouble)percentBusUtilization, - (jint)busOffCount, (jint)txFullCount, - (jint)receiveErrorCount, (jint)transmitErrorCount); - } + static jmethodID func = env->GetMethodID(canStatusCls, "setStatus", + "(DIIII)V"); + env->CallObjectMethod(canStatus, func, (jdouble)percentBusUtilization, + (jint)busOffCount, (jint)txFullCount, + (jint)receiveErrorCount, (jint)transmitErrorCount); +} + +void SetMatchInfoObject(JNIEnv* env, jobject matchStatus, + const HAL_MatchInfo& matchInfo) { + static jmethodID func = env->GetMethodID(matchInfoDataCls, "setData", + "(Ljava/lang/String;Ljava/lang/String;III)V"); + + env->CallObjectMethod(matchStatus, func, + MakeJString(env, matchInfo.eventName), + MakeJString(env, matchInfo.gameSpecificMessage), + (jint)matchInfo.matchNumber, + (jint)matchInfo.replayNumber, + (jint)matchInfo.matchType); +} } // namespace frc @@ -275,6 +289,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { canStatusCls = JClass(env, "edu/wpi/first/wpilibj/can/CANStatus"); if (!canStatusCls) return JNI_ERR; + matchInfoDataCls = JClass(env, "edu/wpi/first/wpilibj/hal/MatchInfoData"); + if (!matchInfoDataCls) return JNI_ERR; + return JNI_VERSION_1_6; } @@ -295,6 +312,7 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { uncleanStatusExCls.free(env); pwmConfigDataResultCls.free(env); canStatusCls.free(env); + matchInfoDataCls.free(env); jvm = nullptr; } diff --git a/wpilibj/src/main/native/cpp/HALUtil.h b/wpilibj/src/main/native/cpp/HALUtil.h index 8390ecf586..340aa21b41 100644 --- a/wpilibj/src/main/native/cpp/HALUtil.h +++ b/wpilibj/src/main/native/cpp/HALUtil.h @@ -14,11 +14,13 @@ extern JavaVM *jvm; +struct HAL_MatchInfo; + namespace frc { void ReportError(JNIEnv *env, int32_t status, bool doThrow = true); - -void ThrowError(JNIEnv *env, int32_t status, int32_t minRange, int32_t maxRange, + +void ThrowError(JNIEnv *env, int32_t status, int32_t minRange, int32_t maxRange, int32_t requestedValue); inline bool CheckStatus(JNIEnv *env, int32_t status, bool doThrow = true) { @@ -26,7 +28,7 @@ inline bool CheckStatus(JNIEnv *env, int32_t status, bool doThrow = true) { return status == 0; } -inline bool CheckStatusRange(JNIEnv *env, int32_t status, int32_t minRange, +inline bool CheckStatusRange(JNIEnv *env, int32_t status, int32_t minRange, int32_t maxRange, int32_t requestedValue) { if (status != 0) ThrowError(env, status, minRange, maxRange, requestedValue); return status == 0; @@ -47,17 +49,20 @@ inline bool CheckCANStatus(JNIEnv *env, int32_t status, int32_t message_id) { void ThrowIllegalArgumentException(JNIEnv *env, const char *msg); void ThrowBoundaryException(JNIEnv *env, double value, double lower, double upper); - + jobject CreatePWMConfigDataResult(JNIEnv *env, int32_t maxPwm, int32_t deadbandMaxPwm, int32_t centerPwm, int32_t deadbandMinPwm, int32_t minPwm); -void SetCanStatusObject(JNIEnv *env, jobject canStatus, +void SetCanStatusObject(JNIEnv *env, jobject canStatus, float percentBusUtilization, - uint32_t busOffCount, uint32_t txFullCount, - uint32_t receiveErrorCount, + uint32_t busOffCount, uint32_t txFullCount, + uint32_t receiveErrorCount, uint32_t transmitErrorCount); - + +void SetMatchInfoObject(JNIEnv* env, jobject matchStatus, + const HAL_MatchInfo& matchInfo); + } // namespace frc #endif // HALUTIL_H diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/hal/MatchInfoDataTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/hal/MatchInfoDataTest.java new file mode 100644 index 0000000000..666ecb1b40 --- /dev/null +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/hal/MatchInfoDataTest.java @@ -0,0 +1,19 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 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. */ +/*----------------------------------------------------------------------------*/ + +package edu.wpi.first.wpilibj.hal; + +import org.junit.Test; + +public class MatchInfoDataTest { + @Test + public void matchInfoDataDoesNotThrow() { + MatchInfoData data = new MatchInfoData(); + HAL.getMatchInfo(data); + // Nothing we can assert, so just make sure it didn't throw. + } +}