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.
This commit is contained in:
Peter Johnson
2017-11-14 00:00:45 -08:00
parent df7c1389de
commit 6307d41002
11 changed files with 168 additions and 73 deletions

View File

@@ -57,6 +57,7 @@ static JException uncleanStatusExCls;
static JClass pwmConfigDataResultCls;
static JClass canStatusCls;
static JClass matchInfoDataCls;
static JClass accumulatorResultCls;
namespace frc {
@@ -234,6 +235,14 @@ void SetMatchInfoObject(JNIEnv* env, jobject matchStatus,
(jint)matchInfo.matchType);
}
void SetAccumulatorResultObject(JNIEnv* env, jobject accumulatorResult,
int64_t value, int64_t count) {
static jmethodID func = env->GetMethodID(accumulatorResultCls, "set",
"(JJ)V");
env->CallObjectMethod(accumulatorResult, func, (jlong)value, (jlong)count);
}
} // namespace frc
using namespace frc;
@@ -292,6 +301,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
matchInfoDataCls = JClass(env, "edu/wpi/first/wpilibj/hal/MatchInfoData");
if (!matchInfoDataCls) return JNI_ERR;
accumulatorResultCls = JClass(env, "edu/wpi/first/wpilibj/AccumulatorResult");
if (!accumulatorResultCls) return JNI_ERR;
return JNI_VERSION_1_6;
}

View File

@@ -63,6 +63,9 @@ void SetCanStatusObject(JNIEnv *env, jobject canStatus,
void SetMatchInfoObject(JNIEnv* env, jobject matchStatus,
const HAL_MatchInfo& matchInfo);
void SetAccumulatorResultObject(JNIEnv* env, jobject accumulatorResult,
int64_t value, int64_t count);
} // namespace frc
#endif // HALUTIL_H

View File

@@ -13,8 +13,10 @@
#include "HAL/SPI.h"
#include "HALUtil.h"
#include "support/jni_util.h"
using namespace frc;
using namespace wpi::java;
// set the logging level
TLogLevel spiJNILogLevel = logWARNING;
@@ -66,6 +68,30 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SPIJNI_spiTransaction(
return retVal;
}
/*
* Class: edu_wpi_first_wpilibj_hal_SPIJNI
* Method: spiTransactionB
* Signature: (I[B[BB)I
*/
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SPIJNI_spiTransactionB(
JNIEnv *env, jclass, jint port, jbyteArray dataToSend, jbyteArray dataReceived,
jbyte size) {
SPIJNI_LOG(logDEBUG) << "Calling SPIJNI spiTransactionB";
SPIJNI_LOG(logDEBUG) << "Port = " << (jint)port;
SPIJNI_LOG(logDEBUG) << "Size = " << (jint)size;
llvm::SmallVector<uint8_t, 128> recvBuf;
recvBuf.resize(size);
jint retVal =
HAL_TransactionSPI(static_cast<HAL_SPIPort>(port),
reinterpret_cast<const uint8_t *>(
JByteArrayRef(env, dataToSend).array().data()),
recvBuf.data(), size);
env->SetByteArrayRegion(dataReceived, 0, size,
reinterpret_cast<const jbyte *>(recvBuf.data()));
SPIJNI_LOG(logDEBUG) << "ReturnValue = " << (jint)retVal;
return retVal;
}
/*
* Class: edu_wpi_first_wpilibj_hal_SPIJNI
* Method: spiWrite
@@ -86,20 +112,73 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SPIJNI_spiWrite(
return retVal;
}
/*
* Class: edu_wpi_first_wpilibj_hal_SPIJNI
* Method: spiWriteB
* Signature: (I[BB)I
*/
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SPIJNI_spiWriteB(
JNIEnv *env, jclass, jint port, jbyteArray dataToSend, jbyte size) {
SPIJNI_LOG(logDEBUG) << "Calling SPIJNI spiWriteB";
SPIJNI_LOG(logDEBUG) << "Port = " << (jint)port;
SPIJNI_LOG(logDEBUG) << "Size = " << (jint)size;
jint retVal = HAL_WriteSPI(static_cast<HAL_SPIPort>(port),
reinterpret_cast<const uint8_t *>(
JByteArrayRef(env, dataToSend).array().data()),
size);
SPIJNI_LOG(logDEBUG) << "ReturnValue = " << (jint)retVal;
return retVal;
}
/*
* Class: edu_wpi_first_wpilibj_hal_SPIJNI
* Method: spiRead
* Signature: (ILjava/nio/ByteBuffer;B)I
* Signature: (IZLjava/nio/ByteBuffer;B)I
*/
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SPIJNI_spiRead(
JNIEnv *env, jclass, jint port, jobject dataReceived, jbyte size) {
JNIEnv *env, jclass, jint port, jboolean initiate, jobject dataReceived, jbyte size) {
SPIJNI_LOG(logDEBUG) << "Calling SPIJNI spiRead";
SPIJNI_LOG(logDEBUG) << "Port = " << (jint)port;
SPIJNI_LOG(logDEBUG) << "Initiate = " << (jboolean)initiate;
uint8_t *dataReceivedPtr =
(uint8_t *)env->GetDirectBufferAddress(dataReceived);
SPIJNI_LOG(logDEBUG) << "Size = " << (jint)size;
SPIJNI_LOG(logDEBUG) << "DataReceivedPtr = " << dataReceivedPtr;
jint retVal = HAL_ReadSPI(static_cast<HAL_SPIPort>(port), (uint8_t *)dataReceivedPtr, size);
jint retVal;
if (initiate) {
llvm::SmallVector<uint8_t, 128> sendBuf;
sendBuf.resize(size);
retVal = HAL_TransactionSPI(static_cast<HAL_SPIPort>(port), sendBuf.data(), dataReceivedPtr, size);
} else {
retVal = HAL_ReadSPI(static_cast<HAL_SPIPort>(port), (uint8_t *)dataReceivedPtr, size);
}
SPIJNI_LOG(logDEBUG) << "ReturnValue = " << (jint)retVal;
return retVal;
}
/*
* Class: edu_wpi_first_wpilibj_hal_SPIJNI
* Method: spiReadB
* Signature: (IZ[BB)I
*/
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SPIJNI_spiReadB(
JNIEnv *env, jclass, jint port, jboolean initiate, jbyteArray dataReceived, jbyte size) {
SPIJNI_LOG(logDEBUG) << "Calling SPIJNI spiReadB";
SPIJNI_LOG(logDEBUG) << "Port = " << (jint)port;
SPIJNI_LOG(logDEBUG) << "Initiate = " << (jboolean)initiate;
SPIJNI_LOG(logDEBUG) << "Size = " << (jint)size;
jint retVal;
llvm::SmallVector<uint8_t, 128> recvBuf;
recvBuf.resize(size);
if (initiate) {
llvm::SmallVector<uint8_t, 128> sendBuf;
sendBuf.resize(size);
retVal = HAL_TransactionSPI(static_cast<HAL_SPIPort>(port), sendBuf.data(), recvBuf.data(), size);
} else {
retVal = HAL_ReadSPI(static_cast<HAL_SPIPort>(port), recvBuf.data(), size);
}
env->SetByteArrayRegion(dataReceived, 0, size,
reinterpret_cast<const jbyte *>(recvBuf.data()));
SPIJNI_LOG(logDEBUG) << "ReturnValue = " << (jint)retVal;
return retVal;
}
@@ -344,29 +423,23 @@ Java_edu_wpi_first_wpilibj_hal_SPIJNI_spiGetAccumulatorAverage(
/*
* Class: edu_wpi_first_wpilibj_hal_SPIJNI
* Method: spiGetAccumulatorOutput
* Signature: (ILjava/nio/LongBuffer;Ljava/nio/LongBuffer;)V
* Signature: (ILedu/wpi/first/wpilibj/AccumulatorResult;)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_wpilibj_hal_SPIJNI_spiGetAccumulatorOutput(
JNIEnv *env, jclass, jint port, jobject value, jobject count) {
JNIEnv *env, jclass, jint port, jobject accumulatorResult) {
SPIJNI_LOG(logDEBUG) << "Calling SPIJNI spiGetAccumulatorOutput";
SPIJNI_LOG(logDEBUG) << "Port = " << (jint)port;
int32_t status = 0;
int64_t value = 0;
int64_t count = 0;
HAL_GetSPIAccumulatorOutput(static_cast<HAL_SPIPort>(port), &value, &count, &status);
jlong *valuePtr = (jlong *)env->GetDirectBufferAddress(value);
jlong *countPtr = (jlong *)env->GetDirectBufferAddress(count);
int64_t valueInt64;
int64_t countInt64;
HAL_GetSPIAccumulatorOutput(static_cast<HAL_SPIPort>(port), &valueInt64, &countInt64, &status);
*valuePtr = valueInt64;
*countPtr = countInt64;
SetAccumulatorResultObject(env, accumulatorResult, value, count);
SPIJNI_LOG(logDEBUG) << "Status = " << status;
SPIJNI_LOG(logDEBUG) << "Value = " << *valuePtr;
SPIJNI_LOG(logDEBUG) << "Count = " << *countPtr;
SPIJNI_LOG(logDEBUG) << "Value = " << value;
SPIJNI_LOG(logDEBUG) << "Count = " << count;
CheckStatus(env, status);
}