Adds match specific calls to Java and C++ (#720)

Uses caching, matching the joystick calls.
This commit is contained in:
Thad House
2017-11-09 19:59:29 -08:00
committed by Peter Johnson
parent 2225c4fee2
commit 7bbd13d914
9 changed files with 310 additions and 51 deletions

View File

@@ -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<std::mutex> lock(m_joystickDataMutex);
std::unique_lock<std::mutex> 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<std::mutex> lock(m_joystickDataMutex);
std::unique_lock<std::mutex> 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<std::mutex> lock(m_joystickDataMutex);
std::unique_lock<std::mutex> 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<std::mutex> lock(m_joystickDataMutex);
std::unique_lock<std::mutex> 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<std::mutex> lock(m_joystickDataMutex);
std::unique_lock<std::mutex> 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<std::mutex> lock(m_joystickDataMutex);
std::lock_guard<std::mutex> 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<std::mutex> lock(m_joystickDataMutex);
std::lock_guard<std::mutex> 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<std::mutex> lock(m_joystickDataMutex);
std::lock_guard<std::mutex> 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<std::mutex> lock(m_joystickDataMutex);
std::lock_guard<std::mutex> 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<std::mutex> lock(m_joystickDataMutex);
std::lock_guard<std::mutex> lock(m_cacheDataMutex);
return static_cast<bool>(m_joystickDescriptor[stick].isXbox);
}
@@ -321,7 +331,7 @@ int DriverStation::GetJoystickType(int stick) const {
wpi_setWPIError(BadJoystickIndex);
return -1;
}
std::lock_guard<std::mutex> lock(m_joystickDataMutex);
std::lock_guard<std::mutex> lock(m_cacheDataMutex);
return static_cast<int>(m_joystickDescriptor[stick].type);
}
@@ -335,7 +345,7 @@ std::string DriverStation::GetJoystickName(int stick) const {
if (stick >= kJoystickPorts) {
wpi_setWPIError(BadJoystickIndex);
}
std::lock_guard<std::mutex> lock(m_joystickDataMutex);
std::lock_guard<std::mutex> 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<std::mutex> lock(m_joystickDataMutex);
std::lock_guard<std::mutex> 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<std::mutex> lock(m_cacheDataMutex);
return m_matchInfo->gameSpecificMessage;
}
std::string DriverStation::GetEventName() const {
std::lock_guard<std::mutex> lock(m_cacheDataMutex);
return m_matchInfo->eventName;
}
DriverStation::MatchType DriverStation::GetMatchType() const {
std::lock_guard<std::mutex> lock(m_cacheDataMutex);
return m_matchInfo->matchType;
}
int DriverStation::GetMatchNumber() const {
std::lock_guard<std::mutex> lock(m_cacheDataMutex);
return m_matchInfo->matchNumber;
}
int DriverStation::GetReplayNumber() const {
std::lock_guard<std::mutex> 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<DriverStation::MatchType>(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<std::mutex> lock(m_joystickDataMutex);
std::lock_guard<std::mutex> 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<HAL_JoystickButtons[]>(kJoystickPorts);
m_joystickDescriptor =
std::make_unique<HAL_JoystickDescriptor[]>(kJoystickPorts);
m_matchInfo = std::make_unique<MatchInfoData>();
m_joystickAxesCache = std::make_unique<HAL_JoystickAxes[]>(kJoystickPorts);
m_joystickPOVsCache = std::make_unique<HAL_JoystickPOVs[]>(kJoystickPorts);
m_joystickButtonsCache =
std::make_unique<HAL_JoystickButtons[]>(kJoystickPorts);
m_joystickDescriptorCache =
std::make_unique<HAL_JoystickDescriptor[]>(kJoystickPorts);
m_matchInfoCache = std::make_unique<MatchInfoData>();
// All joysticks should default to having zero axes, povs and buttons, so
// uninitialized memory doesn't get sent to speed controllers.

View File

@@ -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<HAL_JoystickPOVs[]> m_joystickPOVs;
std::unique_ptr<HAL_JoystickButtons[]> m_joystickButtons;
std::unique_ptr<HAL_JoystickDescriptor[]> m_joystickDescriptor;
std::unique_ptr<MatchInfoData> m_matchInfo;
// Joystick Cached Data
std::unique_ptr<HAL_JoystickAxes[]> m_joystickAxesCache;
std::unique_ptr<HAL_JoystickPOVs[]> m_joystickPOVsCache;
std::unique_ptr<HAL_JoystickButtons[]> m_joystickButtonsCache;
std::unique_ptr<HAL_JoystickDescriptor[]> m_joystickDescriptorCache;
std::unique_ptr<MatchInfoData> m_matchInfoCache;
// Joystick button rising/falling edge flags
std::array<uint32_t, kJoystickPorts> m_joystickButtonsPressed;
@@ -124,7 +135,7 @@ class DriverStation : public SensorBase, public RobotStateInterface {
std::thread m_dsThread;
std::atomic<bool> m_isRunning{false};
mutable std::mutex m_joystickDataMutex;
mutable std::mutex m_cacheDataMutex;
// Robot state status variables
bool m_userInDisabled = false;

View File

@@ -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;
}
}

View File

@@ -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,

View File

@@ -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;
}
}

View File

@@ -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<jboolean>(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<jboolean>(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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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.
}
}