mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-27 02:01:42 +00:00
[hal, wpilib] Rewrite CAN APIs (#7798)
This commit is contained in:
@@ -19,29 +19,20 @@ using namespace wpi::java;
|
||||
|
||||
extern "C" {
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_CANAPIJNI
|
||||
* Method: getCANPacketBaseTime
|
||||
* Signature: ()J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_edu_wpi_first_hal_CANAPIJNI_getCANPacketBaseTime
|
||||
(JNIEnv*, jclass)
|
||||
{
|
||||
return HAL_GetCANPacketBaseTime();
|
||||
}
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_CANAPIJNI
|
||||
* Method: initializeCAN
|
||||
* Signature: (III)I
|
||||
* Signature: (IIII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_CANAPIJNI_initializeCAN
|
||||
(JNIEnv* env, jclass, jint manufacturer, jint deviceId, jint deviceType)
|
||||
(JNIEnv* env, jclass, jint busId, jint manufacturer, jint deviceId,
|
||||
jint deviceType)
|
||||
{
|
||||
int32_t status = 0;
|
||||
auto handle =
|
||||
HAL_InitializeCAN(static_cast<HAL_CANManufacturer>(manufacturer),
|
||||
HAL_InitializeCAN(static_cast<int32_t>(busId),
|
||||
static_cast<HAL_CANManufacturer>(manufacturer),
|
||||
static_cast<int32_t>(deviceId),
|
||||
static_cast<HAL_CANDeviceType>(deviceType), &status);
|
||||
|
||||
@@ -63,105 +54,189 @@ Java_edu_wpi_first_hal_CANAPIJNI_cleanCAN
|
||||
}
|
||||
}
|
||||
|
||||
static bool PackCANMessage(JNIEnv* env, jbyteArray data, jint dataLength,
|
||||
jint flags, HAL_CANMessage* message) {
|
||||
if (data == nullptr) {
|
||||
ThrowNullPointerException(env, "data array cannot be null");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto arrLen = env->GetArrayLength(data);
|
||||
if (arrLen < dataLength) {
|
||||
ThrowIllegalArgumentException(env, "array length less than data length");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((flags & HAL_CAN_FD_DATALENGTH) && dataLength > 64) {
|
||||
ThrowIllegalArgumentException(env, "FD frame has max length of 64 bytes");
|
||||
return false;
|
||||
} else if (!(flags & HAL_CAN_FD_DATALENGTH) && dataLength > 8) {
|
||||
ThrowIllegalArgumentException(env,
|
||||
"Non FD frame has max length of 8 bytes");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::memset(message, 0, sizeof(*message));
|
||||
message->dataSize = dataLength;
|
||||
message->flags = flags;
|
||||
JSpan<const jbyte> arr{env, data, static_cast<size_t>(dataLength)};
|
||||
std::memcpy(message->data, arr.data(), dataLength);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_CANAPIJNI
|
||||
* Method: writeCANPacket
|
||||
* Signature: (I[BI)V
|
||||
* Signature: (II[BII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_CANAPIJNI_writeCANPacket
|
||||
(JNIEnv* env, jclass, jint handle, jbyteArray data, jint apiId)
|
||||
(JNIEnv* env, jclass, jint handle, jint apiId, jbyteArray data,
|
||||
jint dataLength, jint flags)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
JSpan<const jbyte> arr{env, data};
|
||||
HAL_CANMessage message;
|
||||
if (!PackCANMessage(env, data, dataLength, flags, &message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacket(halHandle, reinterpret_cast<const uint8_t*>(arr.data()),
|
||||
arr.size(), apiId, &status);
|
||||
HAL_WriteCANPacket(static_cast<HAL_CANHandle>(handle), apiId, &message,
|
||||
&status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_CANAPIJNI
|
||||
* Method: writeCANPacketRepeating
|
||||
* Signature: (I[BII)V
|
||||
* Signature: (II[BIII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_CANAPIJNI_writeCANPacketRepeating
|
||||
(JNIEnv* env, jclass, jint handle, jbyteArray data, jint apiId,
|
||||
jint timeoutMs)
|
||||
(JNIEnv* env, jclass, jint handle, jint apiId, jbyteArray data,
|
||||
jint dataLength, jint flags, jint repeatMs)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
JSpan<const jbyte> arr{env, data};
|
||||
HAL_CANMessage message;
|
||||
if (!PackCANMessage(env, data, dataLength, flags, &message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacketRepeating(halHandle,
|
||||
reinterpret_cast<const uint8_t*>(arr.data()),
|
||||
arr.size(), apiId, timeoutMs, &status);
|
||||
HAL_WriteCANPacketRepeating(static_cast<HAL_CANHandle>(handle), apiId,
|
||||
&message, repeatMs, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_CANAPIJNI
|
||||
* Method: writeCANRTRFrame
|
||||
* Signature: (III)V
|
||||
* Signature: (II[BII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_CANAPIJNI_writeCANRTRFrame
|
||||
(JNIEnv* env, jclass, jint handle, jint length, jint apiId)
|
||||
(JNIEnv* env, jclass, jint handle, jint apiId, jbyteArray data,
|
||||
jint dataLength, jint flags)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
HAL_CANMessage message;
|
||||
|
||||
if (data == nullptr) {
|
||||
// We will allow RTR frames to have a null data array
|
||||
if ((flags & HAL_CAN_FD_DATALENGTH) && dataLength > 64) {
|
||||
ThrowIllegalArgumentException(env, "FD frame has max length of 64 bytes");
|
||||
return;
|
||||
} else if (!(flags & HAL_CAN_FD_DATALENGTH) && dataLength > 8) {
|
||||
ThrowIllegalArgumentException(env,
|
||||
"Non FD frame has max length of 8 bytes");
|
||||
return;
|
||||
}
|
||||
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.flags = flags;
|
||||
message.dataSize = dataLength;
|
||||
} else if (!PackCANMessage(env, data, dataLength, flags, &message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANRTRFrame(halHandle, static_cast<int32_t>(length), apiId, &status);
|
||||
HAL_WriteCANRTRFrame(static_cast<HAL_CANHandle>(handle), apiId, &message,
|
||||
&status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_CANAPIJNI
|
||||
* Method: writeCANPacketNoThrow
|
||||
* Signature: (I[BI)I
|
||||
* Signature: (II[BII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_CANAPIJNI_writeCANPacketNoThrow
|
||||
(JNIEnv* env, jclass, jint handle, jbyteArray data, jint apiId)
|
||||
(JNIEnv* env, jclass, jint handle, jint apiId, jbyteArray data,
|
||||
jint dataLength, jint flags)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
JSpan<const jbyte> arr{env, data};
|
||||
HAL_CANMessage message;
|
||||
if (!PackCANMessage(env, data, dataLength, flags, &message)) {
|
||||
return PARAMETER_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacket(halHandle, reinterpret_cast<const uint8_t*>(arr.data()),
|
||||
arr.size(), apiId, &status);
|
||||
HAL_WriteCANPacket(static_cast<HAL_CANHandle>(handle), apiId, &message,
|
||||
&status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_CANAPIJNI
|
||||
* Method: writeCANPacketRepeatingNoThrow
|
||||
* Signature: (I[BII)I
|
||||
* Signature: (II[BIII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_CANAPIJNI_writeCANPacketRepeatingNoThrow
|
||||
(JNIEnv* env, jclass, jint handle, jbyteArray data, jint apiId,
|
||||
jint timeoutMs)
|
||||
(JNIEnv* env, jclass, jint handle, jint apiId, jbyteArray data,
|
||||
jint dataLength, jint flags, jint repeatMs)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
JSpan<const jbyte> arr{env, data};
|
||||
HAL_CANMessage message;
|
||||
if (!PackCANMessage(env, data, dataLength, flags, &message)) {
|
||||
return PARAMETER_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacketRepeating(halHandle,
|
||||
reinterpret_cast<const uint8_t*>(arr.data()),
|
||||
arr.size(), apiId, timeoutMs, &status);
|
||||
HAL_WriteCANPacketRepeating(static_cast<HAL_CANHandle>(handle), apiId,
|
||||
&message, repeatMs, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_CANAPIJNI
|
||||
* Method: writeCANRTRFrameNoThrow
|
||||
* Signature: (III)I
|
||||
* Signature: (II[BII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_CANAPIJNI_writeCANRTRFrameNoThrow
|
||||
(JNIEnv* env, jclass, jint handle, jint length, jint apiId)
|
||||
(JNIEnv* env, jclass, jint handle, jint apiId, jbyteArray data,
|
||||
jint dataLength, jint flags)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
HAL_CANMessage message;
|
||||
|
||||
if (data == nullptr) {
|
||||
// We will allow RTR frames to have a null data array
|
||||
if ((flags & HAL_CAN_FD_DATALENGTH) && dataLength > 64) {
|
||||
ThrowIllegalArgumentException(env, "FD frame has max length of 64 bytes");
|
||||
return PARAMETER_OUT_OF_RANGE;
|
||||
} else if (!(flags & HAL_CAN_FD_DATALENGTH) && dataLength > 8) {
|
||||
ThrowIllegalArgumentException(env,
|
||||
"Non FD frame has max length of 8 bytes");
|
||||
return PARAMETER_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.flags = flags;
|
||||
message.dataSize = dataLength;
|
||||
} else if (!PackCANMessage(env, data, dataLength, flags, &message)) {
|
||||
return PARAMETER_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANRTRFrame(halHandle, static_cast<int32_t>(length), apiId, &status);
|
||||
HAL_WriteCANRTRFrame(static_cast<HAL_CANHandle>(handle), apiId, &message,
|
||||
&status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -190,29 +265,28 @@ Java_edu_wpi_first_hal_CANAPIJNI_readCANPacketNew
|
||||
(JNIEnv* env, jclass, jint handle, jint apiId, jobject data)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
uint8_t dataTemp[8];
|
||||
int32_t dataLength = 0;
|
||||
uint64_t timestamp = 0;
|
||||
HAL_CANReceiveMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
int32_t status = 0;
|
||||
HAL_ReadCANPacketNew(halHandle, apiId, dataTemp, &dataLength, ×tamp,
|
||||
&status);
|
||||
HAL_ReadCANPacketNew(halHandle, apiId, &message, &status);
|
||||
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
|
||||
return false;
|
||||
}
|
||||
if (!CheckStatus(env, status)) {
|
||||
return false;
|
||||
}
|
||||
if (dataLength > 8) {
|
||||
dataLength = 8;
|
||||
}
|
||||
|
||||
jbyteArray toSetArray = SetCANDataObject(env, data, dataLength, timestamp);
|
||||
jbyteArray toSetArray =
|
||||
SetCANReceiveMessageObject(env, data, message.message.dataSize,
|
||||
message.message.flags, message.timeStamp);
|
||||
auto javaLen = env->GetArrayLength(toSetArray);
|
||||
if (javaLen < dataLength) {
|
||||
dataLength = javaLen;
|
||||
if (javaLen < message.message.dataSize) {
|
||||
ThrowIllegalArgumentException(env,
|
||||
"Message buffer not long enough for message");
|
||||
return false;
|
||||
}
|
||||
env->SetByteArrayRegion(toSetArray, 0, dataLength,
|
||||
reinterpret_cast<jbyte*>(dataTemp));
|
||||
env->SetByteArrayRegion(toSetArray, 0, message.message.dataSize,
|
||||
reinterpret_cast<jbyte*>(message.message.data));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -226,48 +300,45 @@ Java_edu_wpi_first_hal_CANAPIJNI_readCANPacketLatest
|
||||
(JNIEnv* env, jclass, jint handle, jint apiId, jobject data)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
uint8_t dataTemp[8];
|
||||
int32_t dataLength = 0;
|
||||
uint64_t timestamp = 0;
|
||||
HAL_CANReceiveMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
int32_t status = 0;
|
||||
HAL_ReadCANPacketLatest(halHandle, apiId, dataTemp, &dataLength, ×tamp,
|
||||
&status);
|
||||
HAL_ReadCANPacketLatest(halHandle, apiId, &message, &status);
|
||||
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
|
||||
return false;
|
||||
}
|
||||
if (!CheckStatus(env, status)) {
|
||||
return false;
|
||||
}
|
||||
if (dataLength > 8) {
|
||||
dataLength = 8;
|
||||
}
|
||||
|
||||
jbyteArray toSetArray = SetCANDataObject(env, data, dataLength, timestamp);
|
||||
jbyteArray toSetArray =
|
||||
SetCANReceiveMessageObject(env, data, message.message.dataSize,
|
||||
message.message.flags, message.timeStamp);
|
||||
auto javaLen = env->GetArrayLength(toSetArray);
|
||||
if (javaLen < dataLength) {
|
||||
dataLength = javaLen;
|
||||
if (javaLen < message.message.dataSize) {
|
||||
ThrowIllegalArgumentException(env,
|
||||
"Message buffer not long enough for message");
|
||||
return false;
|
||||
}
|
||||
env->SetByteArrayRegion(toSetArray, 0, dataLength,
|
||||
reinterpret_cast<jbyte*>(dataTemp));
|
||||
env->SetByteArrayRegion(toSetArray, 0, message.message.dataSize,
|
||||
reinterpret_cast<jbyte*>(message.message.data));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_CANAPIJNI
|
||||
* Method: readCANPacketTimeout
|
||||
* Signature: (IIILjava/lang/Object;)Z
|
||||
* Signature: (IILjava/lang/Object;I)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_hal_CANAPIJNI_readCANPacketTimeout
|
||||
(JNIEnv* env, jclass, jint handle, jint apiId, jint timeoutMs, jobject data)
|
||||
(JNIEnv* env, jclass, jint handle, jint apiId, jobject data, jint timeoutMs)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
uint8_t dataTemp[8];
|
||||
int32_t dataLength = 0;
|
||||
uint64_t timestamp = 0;
|
||||
HAL_CANReceiveMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
int32_t status = 0;
|
||||
HAL_ReadCANPacketTimeout(halHandle, apiId, dataTemp, &dataLength, ×tamp,
|
||||
timeoutMs, &status);
|
||||
HAL_ReadCANPacketTimeout(halHandle, apiId, &message, timeoutMs, &status);
|
||||
if (status == HAL_CAN_TIMEOUT ||
|
||||
status == HAL_ERR_CANSessionMux_MessageNotFound) {
|
||||
return false;
|
||||
@@ -275,17 +346,18 @@ Java_edu_wpi_first_hal_CANAPIJNI_readCANPacketTimeout
|
||||
if (!CheckStatus(env, status)) {
|
||||
return false;
|
||||
}
|
||||
if (dataLength > 8) {
|
||||
dataLength = 8;
|
||||
}
|
||||
|
||||
jbyteArray toSetArray = SetCANDataObject(env, data, dataLength, timestamp);
|
||||
jbyteArray toSetArray =
|
||||
SetCANReceiveMessageObject(env, data, message.message.dataSize,
|
||||
message.message.flags, message.timeStamp);
|
||||
auto javaLen = env->GetArrayLength(toSetArray);
|
||||
if (javaLen < dataLength) {
|
||||
dataLength = javaLen;
|
||||
if (javaLen < message.message.dataSize) {
|
||||
ThrowIllegalArgumentException(env,
|
||||
"Message buffer not long enough for message");
|
||||
return false;
|
||||
}
|
||||
env->SetByteArrayRegion(toSetArray, 0, dataLength,
|
||||
reinterpret_cast<jbyte*>(dataTemp));
|
||||
env->SetByteArrayRegion(toSetArray, 0, message.message.dataSize,
|
||||
reinterpret_cast<jbyte*>(message.message.data));
|
||||
return true;
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
@@ -11,68 +11,98 @@
|
||||
#include "HALUtil.h"
|
||||
#include "edu_wpi_first_hal_can_CANJNI.h"
|
||||
#include "hal/CAN.h"
|
||||
#include "hal/Errors.h"
|
||||
|
||||
using namespace hal;
|
||||
using namespace wpi::java;
|
||||
|
||||
extern "C" {
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_can_CANJNI
|
||||
* Method: FRCNetCommCANSessionMuxSendMessage
|
||||
* Signature: (I[BI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_can_CANJNI_FRCNetCommCANSessionMuxSendMessage
|
||||
(JNIEnv* env, jclass, jint messageID, jbyteArray data, jint periodMs)
|
||||
{
|
||||
JSpan<const jbyte> dataArray{env, data};
|
||||
static bool PackCANMessage(JNIEnv* env, jbyteArray data, jint dataLength,
|
||||
jint flags, HAL_CANMessage* message) {
|
||||
if (data == nullptr) {
|
||||
ThrowNullPointerException(env, "data array cannot be null");
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t* dataBuffer =
|
||||
reinterpret_cast<const uint8_t*>(dataArray.data());
|
||||
uint8_t dataSize = dataArray.size();
|
||||
auto arrLen = env->GetArrayLength(data);
|
||||
if (arrLen < dataLength) {
|
||||
ThrowIllegalArgumentException(env, "array length less than data length");
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t status = 0;
|
||||
HAL_CAN_SendMessage(messageID, dataBuffer, dataSize, periodMs, &status);
|
||||
CheckCANStatus(env, status, messageID);
|
||||
if ((flags & HAL_CAN_FD_DATALENGTH) && dataLength > 64) {
|
||||
ThrowIllegalArgumentException(env, "FD frame has max length of 64 bytes");
|
||||
return false;
|
||||
} else if (!(flags & HAL_CAN_FD_DATALENGTH) && dataLength > 8) {
|
||||
ThrowIllegalArgumentException(env,
|
||||
"Non FD frame has max length of 8 bytes");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::memset(message, 0, sizeof(*message));
|
||||
message->dataSize = dataLength;
|
||||
message->flags = flags;
|
||||
JSpan<const jbyte> arr{env, data, static_cast<size_t>(dataLength)};
|
||||
std::memcpy(message->data, arr.data(), dataLength);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_can_CANJNI
|
||||
* Method: FRCNetCommCANSessionMuxReceiveMessage
|
||||
* Signature: (Ljava/lang/Object;ILjava/lang/Object;)[B
|
||||
* Method: sendMessage
|
||||
* Signature: (II[BIII)I
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_edu_wpi_first_hal_can_CANJNI_FRCNetCommCANSessionMuxReceiveMessage
|
||||
(JNIEnv* env, jclass, jobject messageID, jint messageIDMask,
|
||||
jobject timeStamp)
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_can_CANJNI_sendMessage
|
||||
(JNIEnv* env, jclass, jint busId, jint messageId, jbyteArray data,
|
||||
jint dataLength, jint flags, jint periodMs)
|
||||
{
|
||||
uint32_t* messageIDPtr =
|
||||
reinterpret_cast<uint32_t*>(env->GetDirectBufferAddress(messageID));
|
||||
uint32_t* timeStampPtr =
|
||||
reinterpret_cast<uint32_t*>(env->GetDirectBufferAddress(timeStamp));
|
||||
|
||||
uint8_t dataSize = 0;
|
||||
uint8_t buffer[8];
|
||||
HAL_CANMessage message;
|
||||
if (!PackCANMessage(env, data, dataLength, flags, &message)) {
|
||||
return PARAMETER_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
int32_t status = 0;
|
||||
HAL_CAN_ReceiveMessage(messageIDPtr, messageIDMask, buffer, &dataSize,
|
||||
timeStampPtr, &status);
|
||||
HAL_CAN_SendMessage(busId, messageId, &message, periodMs, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!CheckCANStatus(env, status, *messageIDPtr)) {
|
||||
return nullptr;
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_can_CANJNI
|
||||
* Method: receiveMessage
|
||||
* Signature: (IILjava/lang/Object;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_can_CANJNI_receiveMessage
|
||||
(JNIEnv* env, jclass, jint busId, jint messageId, jobject data)
|
||||
{
|
||||
HAL_CANReceiveMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
int32_t status = 0;
|
||||
HAL_CAN_ReceiveMessage(busId, messageId, &message, &status);
|
||||
jbyteArray toSetArray =
|
||||
SetCANReceiveMessageObject(env, data, message.message.dataSize,
|
||||
message.message.flags, message.timeStamp);
|
||||
auto javaLen = env->GetArrayLength(toSetArray);
|
||||
if (javaLen < message.message.dataSize) {
|
||||
ThrowIllegalArgumentException(env,
|
||||
"Message buffer not long enough for message");
|
||||
return status;
|
||||
}
|
||||
return MakeJByteArray(env, {buffer, static_cast<size_t>(dataSize)});
|
||||
env->SetByteArrayRegion(toSetArray, 0, message.message.dataSize,
|
||||
reinterpret_cast<jbyte*>(message.message.data));
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_can_CANJNI
|
||||
* Method: getCANStatus
|
||||
* Signature: (Ljava/lang/Object;)V
|
||||
* Signature: (ILjava/lang/Object;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_can_CANJNI_getCANStatus
|
||||
(JNIEnv* env, jclass, jobject canStatus)
|
||||
(JNIEnv* env, jclass, jint busId, jobject canStatus)
|
||||
{
|
||||
float percentBusUtilization = 0;
|
||||
uint32_t busOffCount = 0;
|
||||
@@ -80,8 +110,9 @@ Java_edu_wpi_first_hal_can_CANJNI_getCANStatus
|
||||
uint32_t receiveErrorCount = 0;
|
||||
uint32_t transmitErrorCount = 0;
|
||||
int32_t status = 0;
|
||||
HAL_CAN_GetCANStatus(&percentBusUtilization, &busOffCount, &txFullCount,
|
||||
&receiveErrorCount, &transmitErrorCount, &status);
|
||||
HAL_CAN_GetCANStatus(busId, &percentBusUtilization, &busOffCount,
|
||||
&txFullCount, &receiveErrorCount, &transmitErrorCount,
|
||||
&status);
|
||||
|
||||
if (!CheckStatus(env, status)) {
|
||||
return;
|
||||
@@ -94,17 +125,18 @@ Java_edu_wpi_first_hal_can_CANJNI_getCANStatus
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_can_CANJNI
|
||||
* Method: openCANStreamSession
|
||||
* Signature: (III)I
|
||||
* Signature: (IIII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_can_CANJNI_openCANStreamSession
|
||||
(JNIEnv* env, jclass, jint messageID, jint messageIDMask, jint maxMessages)
|
||||
(JNIEnv* env, jclass, jint busId, jint messageId, jint messageIDMask,
|
||||
jint maxMessages)
|
||||
{
|
||||
uint32_t handle = 0;
|
||||
int32_t status = 0;
|
||||
HAL_CAN_OpenStreamSession(&handle, static_cast<uint32_t>(messageID),
|
||||
static_cast<uint32_t>(messageIDMask),
|
||||
static_cast<uint32_t>(maxMessages), &status);
|
||||
HAL_CANStreamHandle handle =
|
||||
HAL_CAN_OpenStreamSession(busId, static_cast<uint32_t>(messageId),
|
||||
static_cast<uint32_t>(messageIDMask),
|
||||
static_cast<uint32_t>(maxMessages), &status);
|
||||
|
||||
if (!CheckStatus(env, status)) {
|
||||
return static_cast<jint>(0);
|
||||
@@ -182,14 +214,17 @@ Java_edu_wpi_first_hal_can_CANJNI_readCANStreamSession
|
||||
}
|
||||
}
|
||||
JLocal<jbyteArray> toSetArray{
|
||||
env, SetCANStreamObject(env, elem, msg->dataSize, msg->messageID,
|
||||
msg->timeStamp)};
|
||||
env, SetCANStreamObject(env, elem, msg->message.message.dataSize,
|
||||
msg->messageId, msg->message.timeStamp)};
|
||||
auto javaLen = env->GetArrayLength(toSetArray);
|
||||
if (javaLen < msg->dataSize) {
|
||||
msg->dataSize = javaLen;
|
||||
if (javaLen < msg->message.message.dataSize) {
|
||||
ThrowIllegalArgumentException(
|
||||
env, "Message buffer not long enough for message");
|
||||
return PARAMETER_OUT_OF_RANGE;
|
||||
}
|
||||
env->SetByteArrayRegion(toSetArray, 0, msg->dataSize,
|
||||
reinterpret_cast<jbyte*>(msg->data));
|
||||
env->SetByteArrayRegion(
|
||||
toSetArray, 0, msg->message.message.dataSize,
|
||||
reinterpret_cast<jbyte*>(msg->message.message.data));
|
||||
}
|
||||
|
||||
if (status == HAL_ERR_CANSessionMux_SessionOverrun) {
|
||||
|
||||
@@ -19,15 +19,15 @@ extern "C" {
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_CTREPCMJNI
|
||||
* Method: initialize
|
||||
* Signature: (I)I
|
||||
* Signature: (II)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_CTREPCMJNI_initialize
|
||||
(JNIEnv* env, jclass, jint module)
|
||||
(JNIEnv* env, jclass, jint busId, jint module)
|
||||
{
|
||||
int32_t status = 0;
|
||||
auto stack = wpi::java::GetJavaStackTrace(env, "edu.wpi.first");
|
||||
auto handle = HAL_InitializeCTREPCM(module, stack.c_str(), &status);
|
||||
auto handle = HAL_InitializeCTREPCM(busId, module, stack.c_str(), &status);
|
||||
CheckStatusForceThrow(env, status);
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -41,17 +41,13 @@ static JException illegalArgExCls;
|
||||
static JException boundaryExCls;
|
||||
static JException allocationExCls;
|
||||
static JException halHandleExCls;
|
||||
static JException canInvalidBufferExCls;
|
||||
static JException canMessageNotFoundExCls;
|
||||
static JException canMessageNotAllowedExCls;
|
||||
static JException canNotInitializedExCls;
|
||||
static JException uncleanStatusExCls;
|
||||
static JException nullPointerEx;
|
||||
static JClass powerDistributionVersionCls;
|
||||
static JClass pwmConfigDataResultCls;
|
||||
static JClass canStatusCls;
|
||||
static JClass matchInfoDataCls;
|
||||
static JClass canDataCls;
|
||||
static JClass canReceiveMessageCls;
|
||||
static JClass canStreamMessageCls;
|
||||
static JClass halValueCls;
|
||||
static JClass revPHVersionCls;
|
||||
@@ -63,8 +59,8 @@ static const JClassInit classes[] = {
|
||||
{"edu/wpi/first/hal/PWMConfigDataResult", &pwmConfigDataResultCls},
|
||||
{"edu/wpi/first/hal/can/CANStatus", &canStatusCls},
|
||||
{"edu/wpi/first/hal/MatchInfoData", &matchInfoDataCls},
|
||||
{"edu/wpi/first/hal/CANData", &canDataCls},
|
||||
{"edu/wpi/first/hal/CANStreamMessage", &canStreamMessageCls},
|
||||
{"edu/wpi/first/hal/can/CANReceiveMessage", &canReceiveMessageCls},
|
||||
{"edu/wpi/first/hal/can/CANStreamMessage", &canStreamMessageCls},
|
||||
{"edu/wpi/first/hal/HALValue", &halValueCls},
|
||||
{"edu/wpi/first/hal/REVPHVersion", &revPHVersionCls},
|
||||
{"edu/wpi/first/hal/can/CANStreamOverflowException",
|
||||
@@ -75,13 +71,6 @@ static const JExceptionInit exceptions[] = {
|
||||
{"edu/wpi/first/hal/util/BoundaryException", &boundaryExCls},
|
||||
{"edu/wpi/first/hal/util/AllocationException", &allocationExCls},
|
||||
{"edu/wpi/first/hal/util/HalHandleException", &halHandleExCls},
|
||||
{"edu/wpi/first/hal/can/CANInvalidBufferException", &canInvalidBufferExCls},
|
||||
{"edu/wpi/first/hal/can/CANMessageNotFoundException",
|
||||
&canMessageNotFoundExCls},
|
||||
{"edu/wpi/first/hal/can/CANMessageNotAllowedException",
|
||||
&canMessageNotAllowedExCls},
|
||||
{"edu/wpi/first/hal/can/CANNotInitializedException",
|
||||
&canNotInitializedExCls},
|
||||
{"edu/wpi/first/hal/util/UncleanStatusException", &uncleanStatusExCls},
|
||||
{"java/lang/NullPointerException", &nullPointerEx}};
|
||||
|
||||
@@ -152,64 +141,6 @@ void ThrowError(JNIEnv* env, int32_t status, int32_t minRange, int32_t maxRange,
|
||||
env, fmt::format(" Code: {}. {}", status, lastError).c_str(), status);
|
||||
}
|
||||
|
||||
void ReportCANError(JNIEnv* env, int32_t status, int message_id) {
|
||||
if (status >= 0) {
|
||||
return;
|
||||
}
|
||||
switch (status) {
|
||||
case kRioStatusSuccess:
|
||||
// Everything is ok... don't throw.
|
||||
break;
|
||||
case HAL_ERR_CANSessionMux_InvalidBuffer:
|
||||
case kRIOStatusBufferInvalidSize: {
|
||||
static jmethodID invalidBufConstruct = nullptr;
|
||||
if (!invalidBufConstruct) {
|
||||
invalidBufConstruct =
|
||||
env->GetMethodID(canInvalidBufferExCls, "<init>", "()V");
|
||||
}
|
||||
jobject exception =
|
||||
env->NewObject(canInvalidBufferExCls, invalidBufConstruct);
|
||||
env->Throw(static_cast<jthrowable>(exception));
|
||||
break;
|
||||
}
|
||||
case HAL_ERR_CANSessionMux_MessageNotFound:
|
||||
case kRIOStatusOperationTimedOut: {
|
||||
static jmethodID messageNotFoundConstruct = nullptr;
|
||||
if (!messageNotFoundConstruct) {
|
||||
messageNotFoundConstruct =
|
||||
env->GetMethodID(canMessageNotFoundExCls, "<init>", "()V");
|
||||
}
|
||||
jobject exception =
|
||||
env->NewObject(canMessageNotFoundExCls, messageNotFoundConstruct);
|
||||
env->Throw(static_cast<jthrowable>(exception));
|
||||
break;
|
||||
}
|
||||
case HAL_ERR_CANSessionMux_NotAllowed:
|
||||
case kRIOStatusFeatureNotSupported: {
|
||||
canMessageNotAllowedExCls.Throw(
|
||||
env, fmt::format("MessageID = {}", message_id).c_str());
|
||||
break;
|
||||
}
|
||||
case HAL_ERR_CANSessionMux_NotInitialized:
|
||||
case kRIOStatusResourceNotInitialized: {
|
||||
static jmethodID notInitConstruct = nullptr;
|
||||
if (!notInitConstruct) {
|
||||
notInitConstruct =
|
||||
env->GetMethodID(canNotInitializedExCls, "<init>", "()V");
|
||||
}
|
||||
jobject exception =
|
||||
env->NewObject(canNotInitializedExCls, notInitConstruct);
|
||||
env->Throw(static_cast<jthrowable>(exception));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
uncleanStatusExCls.Throw(
|
||||
env, fmt::format("Fatal status code detected: {}", status).c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThrowNullPointerException(JNIEnv* env, std::string_view msg) {
|
||||
nullPointerEx.Throw(env, msg);
|
||||
}
|
||||
@@ -302,24 +233,27 @@ void SetMatchInfoObject(JNIEnv* env, jobject matchStatus,
|
||||
static_cast<jint>(matchInfo.matchType));
|
||||
}
|
||||
|
||||
jbyteArray SetCANDataObject(JNIEnv* env, jobject canData, int32_t length,
|
||||
uint64_t timestamp) {
|
||||
static jmethodID func = env->GetMethodID(canDataCls, "setData", "(IJ)[B");
|
||||
jbyteArray SetCANReceiveMessageObject(JNIEnv* env, jobject canData,
|
||||
int32_t length, int32_t flags,
|
||||
uint64_t timestamp) {
|
||||
static jmethodID func =
|
||||
env->GetMethodID(canReceiveMessageCls, "setReceiveData", "(IIJ)[B");
|
||||
|
||||
jbyteArray retVal = static_cast<jbyteArray>(env->CallObjectMethod(
|
||||
canData, func, static_cast<jint>(length), static_cast<jlong>(timestamp)));
|
||||
canData, func, static_cast<jint>(length), static_cast<jint>(flags),
|
||||
static_cast<jlong>(timestamp)));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
jbyteArray SetCANStreamObject(JNIEnv* env, jobject canStreamData,
|
||||
int32_t length, uint32_t messageID,
|
||||
int32_t length, uint32_t messageId,
|
||||
uint64_t timestamp) {
|
||||
static jmethodID func =
|
||||
env->GetMethodID(canStreamMessageCls, "setStreamData", "(IIJ)[B");
|
||||
|
||||
jbyteArray retVal = static_cast<jbyteArray>(env->CallObjectMethod(
|
||||
canStreamData, func, static_cast<jint>(length),
|
||||
static_cast<jint>(messageID), static_cast<jlong>(timestamp)));
|
||||
static_cast<jint>(messageId), static_cast<jlong>(timestamp)));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,15 +42,6 @@ inline bool CheckStatusForceThrow(JNIEnv* env, int32_t status) {
|
||||
return status == 0;
|
||||
}
|
||||
|
||||
void ReportCANError(JNIEnv* env, int32_t status, int32_t message_id);
|
||||
|
||||
inline bool CheckCANStatus(JNIEnv* env, int32_t status, int32_t message_id) {
|
||||
if (status != 0) {
|
||||
ReportCANError(env, status, message_id);
|
||||
}
|
||||
return status == 0;
|
||||
}
|
||||
|
||||
void ThrowNullPointerException(JNIEnv* env, std::string_view msg);
|
||||
void ThrowCANStreamOverflowException(JNIEnv* env, jobjectArray messages,
|
||||
jint length);
|
||||
@@ -75,11 +66,12 @@ void SetCanStatusObject(JNIEnv* env, jobject canStatus,
|
||||
void SetMatchInfoObject(JNIEnv* env, jobject matchStatus,
|
||||
const HAL_MatchInfo& matchInfo);
|
||||
|
||||
jbyteArray SetCANDataObject(JNIEnv* env, jobject canData, int32_t length,
|
||||
uint64_t timestamp);
|
||||
jbyteArray SetCANReceiveMessageObject(JNIEnv* env, jobject canData,
|
||||
int32_t length, int32_t flags,
|
||||
uint64_t timestamp);
|
||||
|
||||
jbyteArray SetCANStreamObject(JNIEnv* env, jobject canStreamData,
|
||||
int32_t length, uint32_t messageID,
|
||||
int32_t length, uint32_t messageId,
|
||||
uint64_t timestamp);
|
||||
|
||||
jobject CreateHALValue(JNIEnv* env, const HAL_Value& value);
|
||||
|
||||
@@ -13,6 +13,19 @@
|
||||
using namespace hal;
|
||||
|
||||
extern "C" {
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PortsJNI
|
||||
* Method: getNumCanBuses
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_PortsJNI_getNumCanBuses
|
||||
(JNIEnv*, jclass)
|
||||
{
|
||||
jint value = HAL_GetNumCanBuses();
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PortsJNI
|
||||
* Method: getNumAnalogInputs
|
||||
|
||||
@@ -27,17 +27,17 @@ extern "C" {
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PowerDistributionJNI
|
||||
* Method: initialize
|
||||
* Signature: (II)I
|
||||
* Signature: (III)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_PowerDistributionJNI_initialize
|
||||
(JNIEnv* env, jclass, jint module, jint type)
|
||||
(JNIEnv* env, jclass, jint busId, jint module, jint type)
|
||||
{
|
||||
int32_t status = 0;
|
||||
auto stack = wpi::java::GetJavaStackTrace(env, "edu.wpi.first");
|
||||
auto handle = HAL_InitializePowerDistribution(
|
||||
module, static_cast<HAL_PowerDistributionType>(type), stack.c_str(),
|
||||
&status);
|
||||
busId, module, static_cast<HAL_PowerDistributionType>(type),
|
||||
stack.c_str(), &status);
|
||||
CheckStatusForceThrow(env, status);
|
||||
return static_cast<jint>(handle);
|
||||
}
|
||||
|
||||
@@ -32,15 +32,15 @@ extern "C" {
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_REVPHJNI
|
||||
* Method: initialize
|
||||
* Signature: (I)I
|
||||
* Signature: (II)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_REVPHJNI_initialize
|
||||
(JNIEnv* env, jclass, jint module)
|
||||
(JNIEnv* env, jclass, jint busId, jint module)
|
||||
{
|
||||
int32_t status = 0;
|
||||
auto stack = wpi::java::GetJavaStackTrace(env, "edu.wpi.first");
|
||||
auto handle = HAL_InitializeREVPH(module, stack.c_str(), &status);
|
||||
auto handle = HAL_InitializeREVPH(busId, module, stack.c_str(), &status);
|
||||
CheckStatusForceThrow(env, status);
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hal/CANAPITypes.h>
|
||||
#include <hal/Types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
@@ -13,26 +15,7 @@
|
||||
*/
|
||||
// These are copies of defines located in CANSessionMux.h prepended with HAL_
|
||||
|
||||
/**
|
||||
* Flag for sending a CAN message once.
|
||||
*/
|
||||
#define HAL_CAN_SEND_PERIOD_NO_REPEAT 0
|
||||
|
||||
/**
|
||||
* Flag for stopping periodic CAN message sends.
|
||||
*/
|
||||
#define HAL_CAN_SEND_PERIOD_STOP_REPEATING -1
|
||||
|
||||
/**
|
||||
* Mask for "is frame remote" in message ID.
|
||||
*/
|
||||
#define HAL_CAN_IS_FRAME_REMOTE 0x40000000
|
||||
|
||||
/**
|
||||
* Mask for "is frame 11 bits" in message ID.
|
||||
*/
|
||||
#define HAL_CAN_IS_FRAME_11BIT 0x80000000
|
||||
|
||||
#define HAL_ERR_CANSessionMux_BufferTooLong -44085
|
||||
#define HAL_ERR_CANSessionMux_InvalidBuffer -44086
|
||||
#define HAL_ERR_CANSessionMux_MessageNotFound -44087
|
||||
#define HAL_WARN_CANSessionMux_NoToken 44087
|
||||
@@ -46,19 +29,17 @@
|
||||
* @ingroup hal_capi
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Storage for CAN Stream Messages.
|
||||
*/
|
||||
struct HAL_CANStreamMessage {
|
||||
/** The message ID */
|
||||
uint32_t messageID;
|
||||
/** The packet received timestamp (based off of CLOCK_MONOTONIC) */
|
||||
uint32_t timeStamp;
|
||||
/** The message data */
|
||||
uint8_t data[8];
|
||||
/** The size of the data received (0-8 bytes) */
|
||||
uint8_t dataSize;
|
||||
uint32_t messageId;
|
||||
/** The message */
|
||||
struct HAL_CANReceiveMessage message;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -70,33 +51,31 @@ extern "C" {
|
||||
/**
|
||||
* Sends a CAN message.
|
||||
*
|
||||
* @param[in] messageID the CAN ID to send
|
||||
* @param[in] data the data to send (0-8 bytes)
|
||||
* @param[in] dataSize the size of the data to send (0-8 bytes)
|
||||
* @param[in] periodMs the period to repeat the packet at. Use
|
||||
* HAL_CAN_SEND_PERIOD_NO_REPEAT to not repeat.
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @param[in] busId the CAN bus number
|
||||
* @param[in] messageId the message id
|
||||
* @param[in] message the CAN message
|
||||
* @param[in] periodMs the repeat period
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_CAN_SendMessage(uint32_t messageID, const uint8_t* data,
|
||||
uint8_t dataSize, int32_t periodMs, int32_t* status);
|
||||
void HAL_CAN_SendMessage(int32_t busId, uint32_t messageId,
|
||||
const struct HAL_CANMessage* message, int32_t periodMs,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
* Receives a CAN message.
|
||||
*
|
||||
* @param[out] messageID store for the received message ID
|
||||
* @param[in] messageIDMask the message ID mask to look for
|
||||
* @param[out] data data output (8 bytes)
|
||||
* @param[out] dataSize data length (0-8 bytes)
|
||||
* @param[out] timeStamp the packet received timestamp (based off of
|
||||
* CLOCK_MONOTONIC)
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @param[in] busId The CAN bus number
|
||||
* @param[in] messageId the message id
|
||||
* @param[out] message The CAN message
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_CAN_ReceiveMessage(uint32_t* messageID, uint32_t messageIDMask,
|
||||
uint8_t* data, uint8_t* dataSize,
|
||||
uint32_t* timeStamp, int32_t* status);
|
||||
void HAL_CAN_ReceiveMessage(int32_t busId, uint32_t messageId,
|
||||
struct HAL_CANReceiveMessage* message,
|
||||
int32_t* status);
|
||||
/**
|
||||
* Gets CAN status information.
|
||||
*
|
||||
* @param[in] busId the bus number
|
||||
* @param[out] percentBusUtilization the bus utilization
|
||||
* @param[out] busOffCount the number of bus off errors
|
||||
* @param[out] txFullCount the number of tx full errors
|
||||
@@ -104,8 +83,9 @@ void HAL_CAN_ReceiveMessage(uint32_t* messageID, uint32_t messageIDMask,
|
||||
* @param[out] transmitErrorCount the number of transmit errors
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_CAN_GetCANStatus(float* percentBusUtilization, uint32_t* busOffCount,
|
||||
uint32_t* txFullCount, uint32_t* receiveErrorCount,
|
||||
void HAL_CAN_GetCANStatus(int32_t busId, float* percentBusUtilization,
|
||||
uint32_t* busOffCount, uint32_t* txFullCount,
|
||||
uint32_t* receiveErrorCount,
|
||||
uint32_t* transmitErrorCount, int32_t* status);
|
||||
/** @} */
|
||||
/**
|
||||
@@ -115,22 +95,24 @@ void HAL_CAN_GetCANStatus(float* percentBusUtilization, uint32_t* busOffCount,
|
||||
/**
|
||||
* Opens a CAN stream.
|
||||
*
|
||||
* @param[out] sessionHandle output for the session handle
|
||||
* @param[in] messageID the message ID to read
|
||||
* @param[in] busId the bus number
|
||||
* @param[in] messageId the message ID to read
|
||||
* @param[in] messageIDMask the message ID mask
|
||||
* @param[in] maxMessages the maximum number of messages to stream
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @return the stream handle
|
||||
*/
|
||||
void HAL_CAN_OpenStreamSession(uint32_t* sessionHandle, uint32_t messageID,
|
||||
uint32_t messageIDMask, uint32_t maxMessages,
|
||||
int32_t* status);
|
||||
HAL_CANStreamHandle HAL_CAN_OpenStreamSession(int32_t busId, uint32_t messageId,
|
||||
uint32_t messageIDMask,
|
||||
uint32_t maxMessages,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
* Closes a CAN stream.
|
||||
*
|
||||
* @param sessionHandle the session to close
|
||||
*/
|
||||
void HAL_CAN_CloseStreamSession(uint32_t sessionHandle);
|
||||
void HAL_CAN_CloseStreamSession(HAL_CANStreamHandle sessionHandle);
|
||||
|
||||
/**
|
||||
* Reads a CAN stream message.
|
||||
@@ -141,7 +123,7 @@ void HAL_CAN_CloseStreamSession(uint32_t sessionHandle);
|
||||
* @param[out] messagesRead the number of messages actually read
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_CAN_ReadStreamSession(uint32_t sessionHandle,
|
||||
void HAL_CAN_ReadStreamSession(HAL_CANStreamHandle sessionHandle,
|
||||
struct HAL_CANStreamMessage* messages,
|
||||
uint32_t messagesToRead, uint32_t* messagesRead,
|
||||
int32_t* status);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hal/CAN.h"
|
||||
#include "hal/CANAPITypes.h"
|
||||
#include "hal/Types.h"
|
||||
|
||||
@@ -19,28 +20,20 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Reads the current value of the millisecond-resolution timer that the CAN API
|
||||
* functions use as a time base.
|
||||
*
|
||||
* @return Current value of timer used as a base time by the CAN API in
|
||||
* milliseconds.
|
||||
*/
|
||||
uint32_t HAL_GetCANPacketBaseTime(void);
|
||||
|
||||
/**
|
||||
* Initializes a CAN device.
|
||||
*
|
||||
* These follow the FIRST standard CAN layout.
|
||||
* https://docs.wpilib.org/en/stable/docs/software/can-devices/can-addressing.html
|
||||
*
|
||||
* @param[in] busId the bus id
|
||||
* @param[in] manufacturer the can manufacturer
|
||||
* @param[in] deviceId the device ID (0-63)
|
||||
* @param[in] deviceType the device type
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @return the created CAN handle
|
||||
*/
|
||||
HAL_CANHandle HAL_InitializeCAN(HAL_CANManufacturer manufacturer,
|
||||
HAL_CANHandle HAL_InitializeCAN(int32_t busId, HAL_CANManufacturer manufacturer,
|
||||
int32_t deviceId, HAL_CANDeviceType deviceType,
|
||||
int32_t* status);
|
||||
|
||||
@@ -57,30 +50,28 @@ void HAL_CleanCAN(HAL_CANHandle handle);
|
||||
* This ID is 10 bits.
|
||||
*
|
||||
* @param[in] handle the CAN handle
|
||||
* @param[in] data the data to write (0-8 bytes)
|
||||
* @param[in] length the length of data (0-8)
|
||||
* @param[in] apiId the ID to write (0-1023 bits)
|
||||
* @param[in] apiId the ID to write (0-1023)
|
||||
* @param[in] message the message
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_WriteCANPacket(HAL_CANHandle handle, const uint8_t* data,
|
||||
int32_t length, int32_t apiId, int32_t* status);
|
||||
void HAL_WriteCANPacket(HAL_CANHandle handle, int32_t apiId,
|
||||
const struct HAL_CANMessage* message, int32_t* status);
|
||||
|
||||
/**
|
||||
* Writes a repeating packet to the CAN device with a specific ID.
|
||||
*
|
||||
* This ID is 10 bits.
|
||||
*
|
||||
* The RoboRIO will automatically repeat the packet at the specified interval
|
||||
* The device will automatically repeat the packet at the specified interval
|
||||
*
|
||||
* @param[in] handle the CAN handle
|
||||
* @param[in] data the data to write (0-8 bytes)
|
||||
* @param[in] length the length of data (0-8)
|
||||
* @param[in] apiId the ID to write (0-1023)
|
||||
* @param[in] message the message
|
||||
* @param[in] repeatMs the period to repeat in ms
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_WriteCANPacketRepeating(HAL_CANHandle handle, const uint8_t* data,
|
||||
int32_t length, int32_t apiId,
|
||||
void HAL_WriteCANPacketRepeating(HAL_CANHandle handle, int32_t apiId,
|
||||
const struct HAL_CANMessage* message,
|
||||
int32_t repeatMs, int32_t* status);
|
||||
|
||||
/**
|
||||
@@ -91,11 +82,12 @@ void HAL_WriteCANPacketRepeating(HAL_CANHandle handle, const uint8_t* data,
|
||||
* otherwise behavior is unspecified.
|
||||
*
|
||||
* @param[in] handle the CAN handle
|
||||
* @param[in] length the length of data to request (0-8)
|
||||
* @param[in] apiId the ID to write (0-1023)
|
||||
* @param[in] message the message
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_WriteCANRTRFrame(HAL_CANHandle handle, int32_t length, int32_t apiId,
|
||||
void HAL_WriteCANRTRFrame(HAL_CANHandle handle, int32_t apiId,
|
||||
const struct HAL_CANMessage* message,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
@@ -116,32 +108,26 @@ void HAL_StopCANPacketRepeating(HAL_CANHandle handle, int32_t apiId,
|
||||
* This will only return properly once per packet received. Multiple calls
|
||||
* without receiving another packet will return an error code.
|
||||
*
|
||||
* @param[in] handle the CAN handle
|
||||
* @param[in] apiId the ID to read (0-1023)
|
||||
* @param[out] data the packet data (8 bytes)
|
||||
* @param[out] length the received length (0-8 bytes)
|
||||
* @param[out] receivedTimestamp the packet received timestamp in ms (based off
|
||||
* of CLOCK_MONOTONIC)
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @param[in] handle the CAN handle
|
||||
* @param[in] apiId the ID to read (0-1023)
|
||||
* @param[out] message the message received.
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_ReadCANPacketNew(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
|
||||
int32_t* length, uint64_t* receivedTimestamp,
|
||||
void HAL_ReadCANPacketNew(HAL_CANHandle handle, int32_t apiId,
|
||||
struct HAL_CANReceiveMessage* message,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
* Reads a CAN packet. The will continuously return the last packet received,
|
||||
* without accounting for packet age.
|
||||
*
|
||||
* @param[in] handle the CAN handle
|
||||
* @param[in] apiId the ID to read (0-1023)
|
||||
* @param[out] data the packet data (8 bytes)
|
||||
* @param[out] length the received length (0-8 bytes)
|
||||
* @param[out] receivedTimestamp the packet received timestamp in ms (based off
|
||||
* of CLOCK_MONOTONIC)
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @param[in] handle the CAN handle
|
||||
* @param[in] apiId the ID to read (0-1023)
|
||||
* @param[out] message the message received.
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_ReadCANPacketLatest(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
|
||||
int32_t* length, uint64_t* receivedTimestamp,
|
||||
void HAL_ReadCANPacketLatest(HAL_CANHandle handle, int32_t apiId,
|
||||
struct HAL_CANReceiveMessage* message,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
@@ -149,19 +135,15 @@ void HAL_ReadCANPacketLatest(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
|
||||
* packet is older then the requested timeout. Then it will return an error
|
||||
* code.
|
||||
*
|
||||
* @param[in] handle the CAN handle
|
||||
* @param[in] apiId the ID to read (0-1023)
|
||||
* @param[out] data the packet data (8 bytes)
|
||||
* @param[out] length the received length (0-8 bytes)
|
||||
* @param[out] receivedTimestamp the packet received timestamp in ms (based off
|
||||
* of CLOCK_MONOTONIC)
|
||||
* @param[out] timeoutMs the timeout time for the packet
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @param[in] handle the CAN handle
|
||||
* @param[in] apiId the ID to read (0-1023)
|
||||
* @param[out] message the message received.
|
||||
* @param[out] timeoutMs the timeout time for the packet
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_ReadCANPacketTimeout(HAL_CANHandle handle, int32_t apiId,
|
||||
uint8_t* data, int32_t* length,
|
||||
uint64_t* receivedTimestamp, int32_t timeoutMs,
|
||||
int32_t* status);
|
||||
struct HAL_CANReceiveMessage* message,
|
||||
int32_t timeoutMs, int32_t* status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
@@ -91,4 +91,54 @@ HAL_ENUM(HAL_CANManufacturer) {
|
||||
/// Vivid-Hosting.
|
||||
HAL_CAN_Man_kVividHosting = 16
|
||||
};
|
||||
|
||||
/**
|
||||
* Flag for sending a CAN message once.
|
||||
*/
|
||||
#define HAL_CAN_SEND_PERIOD_NO_REPEAT 0
|
||||
|
||||
/**
|
||||
* Flag for stopping periodic CAN message sends.
|
||||
*/
|
||||
#define HAL_CAN_SEND_PERIOD_STOP_REPEATING -1
|
||||
|
||||
/**
|
||||
* Mask for "is frame remote" in message ID.
|
||||
*/
|
||||
#define HAL_CAN_IS_FRAME_REMOTE 0x40000000
|
||||
|
||||
/**
|
||||
* Mask for "is frame 11 bits" in message ID.
|
||||
*/
|
||||
#define HAL_CAN_IS_FRAME_11BIT 0x80000000
|
||||
|
||||
HAL_ENUM(HAL_CANFlags) {
|
||||
/** Placeholder for no flags */
|
||||
HAL_CAN_NO_FLAGS = 0x0,
|
||||
/**
|
||||
* Mask for if frame will do FD bit rate switching.
|
||||
* Only matters to send.
|
||||
*/
|
||||
HAL_CAN_FD_BITRATESWITCH = 0x1,
|
||||
/**
|
||||
* Mask for is frame will contain an FD length.
|
||||
*/
|
||||
HAL_CAN_FD_DATALENGTH = 0x2,
|
||||
};
|
||||
|
||||
struct HAL_CANMessage {
|
||||
/** Flags for the message (HAL_CANFlags) */
|
||||
int32_t flags;
|
||||
/** The size of the data received (0-64 bytes) */
|
||||
uint8_t dataSize;
|
||||
/** The message data */
|
||||
uint8_t data[64];
|
||||
};
|
||||
|
||||
struct HAL_CANReceiveMessage {
|
||||
/** Receive timestamp (wpi time) */
|
||||
uint64_t timeStamp;
|
||||
/** The received message */
|
||||
struct HAL_CANMessage message;
|
||||
};
|
||||
/** @} */
|
||||
|
||||
@@ -21,13 +21,14 @@ extern "C" {
|
||||
/**
|
||||
* Initializes a PCM.
|
||||
*
|
||||
* @param[in] busId the CAN bus ID
|
||||
* @param[in] module the CAN ID to initialize
|
||||
* @param[in] allocationLocation the location where the allocation is occurring
|
||||
* (can be null)
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @return the created PH handle
|
||||
*/
|
||||
HAL_CTREPCMHandle HAL_InitializeCTREPCM(int32_t module,
|
||||
HAL_CTREPCMHandle HAL_InitializeCTREPCM(int32_t busId, int32_t module,
|
||||
const char* allocationLocation,
|
||||
int32_t* status);
|
||||
|
||||
|
||||
@@ -16,6 +16,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Gets the number of can buses in the current system.
|
||||
*
|
||||
* @return the number of can buses
|
||||
*/
|
||||
int32_t HAL_GetNumCanBuses(void);
|
||||
|
||||
/**
|
||||
* Gets the number of analog inputs in the current system.
|
||||
*
|
||||
|
||||
@@ -37,6 +37,7 @@ extern "C" {
|
||||
/**
|
||||
* Initializes a Power Distribution Panel.
|
||||
*
|
||||
* @param[in] busId the bus id
|
||||
* @param[in] moduleNumber the module number to initialize
|
||||
* @param[in] type the type of module to initialize
|
||||
* @param[in] allocationLocation the location where the allocation is occurring
|
||||
@@ -44,7 +45,7 @@ extern "C" {
|
||||
* @return the created PowerDistribution handle
|
||||
*/
|
||||
HAL_PowerDistributionHandle HAL_InitializePowerDistribution(
|
||||
int32_t moduleNumber, HAL_PowerDistributionType type,
|
||||
int32_t busId, int32_t moduleNumber, HAL_PowerDistributionType type,
|
||||
const char* allocationLocation, int32_t* status);
|
||||
|
||||
/**
|
||||
@@ -412,7 +413,7 @@ void HAL_StartPowerDistributionStream(HAL_PowerDistributionHandle handle,
|
||||
typedef struct HAL_PowerDistributionChannelData {
|
||||
float current;
|
||||
int32_t channel;
|
||||
uint32_t timestamp;
|
||||
uint64_t timestamp;
|
||||
} HAL_PowerDistributionChannelData;
|
||||
|
||||
HAL_PowerDistributionChannelData* HAL_GetPowerDistributionStreamData(
|
||||
|
||||
@@ -137,13 +137,14 @@ extern "C" {
|
||||
/**
|
||||
* Initializes a PH.
|
||||
*
|
||||
* @param[in] busId the bus id
|
||||
* @param[in] module the CAN ID to initialize
|
||||
* @param[in] allocationLocation the location where the allocation is occurring
|
||||
* (can be null)
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @return the created PH handle
|
||||
*/
|
||||
HAL_REVPHHandle HAL_InitializeREVPH(int32_t module,
|
||||
HAL_REVPHHandle HAL_InitializeREVPH(int32_t busId, int32_t module,
|
||||
const char* allocationLocation,
|
||||
int32_t* status);
|
||||
|
||||
|
||||
@@ -68,6 +68,8 @@ typedef HAL_Handle HAL_REVPDHHandle;
|
||||
|
||||
typedef HAL_Handle HAL_REVPHHandle;
|
||||
|
||||
typedef HAL_Handle HAL_CANStreamHandle;
|
||||
|
||||
typedef int32_t HAL_Bool;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -8,31 +8,29 @@
|
||||
#include "hal/Value.h"
|
||||
#include "hal/simulation/NotifyListener.h"
|
||||
|
||||
typedef void (*HAL_CAN_SendMessageCallback)(const char* name, void* param,
|
||||
uint32_t messageID,
|
||||
const uint8_t* data,
|
||||
uint8_t dataSize, int32_t periodMs,
|
||||
int32_t* status);
|
||||
typedef void (*HAL_CAN_SendMessageCallback)(
|
||||
const char* name, void* param, int32_t busId, uint32_t messageId,
|
||||
const struct HAL_CANMessage* message, int32_t periodMs, int32_t* status);
|
||||
|
||||
typedef void (*HAL_CAN_ReceiveMessageCallback)(
|
||||
const char* name, void* param, uint32_t* messageID, uint32_t messageIDMask,
|
||||
uint8_t* data, uint8_t* dataSize, uint32_t* timeStamp, int32_t* status);
|
||||
const char* name, void* param, int32_t busId, uint32_t messageId,
|
||||
struct HAL_CANReceiveMessage* message, int32_t* status);
|
||||
|
||||
typedef void (*HAL_CAN_OpenStreamSessionCallback)(
|
||||
const char* name, void* param, uint32_t* sessionHandle, uint32_t messageID,
|
||||
uint32_t messageIDMask, uint32_t maxMessages, int32_t* status);
|
||||
const char* name, void* param, HAL_CANStreamHandle* streamHandle,
|
||||
int32_t busId, uint32_t messageId, uint32_t messageIDMask,
|
||||
uint32_t maxMessages, int32_t* status);
|
||||
|
||||
typedef void (*HAL_CAN_CloseStreamSessionCallback)(const char* name,
|
||||
void* param,
|
||||
uint32_t sessionHandle);
|
||||
typedef void (*HAL_CAN_CloseStreamSessionCallback)(
|
||||
const char* name, void* param, HAL_CANStreamHandle sessionHandle);
|
||||
|
||||
typedef void (*HAL_CAN_ReadStreamSessionCallback)(
|
||||
const char* name, void* param, uint32_t sessionHandle,
|
||||
const char* name, void* param, HAL_CANStreamHandle sessionHandle,
|
||||
struct HAL_CANStreamMessage* messages, uint32_t messagesToRead,
|
||||
uint32_t* messagesRead, int32_t* status);
|
||||
|
||||
typedef void (*HAL_CAN_GetCANStatusCallback)(
|
||||
const char* name, void* param, float* percentBusUtilization,
|
||||
const char* name, void* param, int32_t busId, float* percentBusUtilization,
|
||||
uint32_t* busOffCount, uint32_t* txFullCount, uint32_t* receiveErrorCount,
|
||||
uint32_t* transmitErrorCount, int32_t* status);
|
||||
|
||||
|
||||
@@ -14,45 +14,50 @@ void InitializeCAN() {}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void HAL_CAN_SendMessage(uint32_t messageID, const uint8_t* data,
|
||||
uint8_t dataSize, int32_t periodMs, int32_t* status) {
|
||||
SimCanData->sendMessage(messageID, data, dataSize, periodMs, status);
|
||||
void HAL_CAN_SendMessage(int32_t busId, uint32_t messageId,
|
||||
const struct HAL_CANMessage* message, int32_t periodMs,
|
||||
int32_t* status) {
|
||||
SimCanData->sendMessage(busId, messageId, message, periodMs, status);
|
||||
}
|
||||
void HAL_CAN_ReceiveMessage(uint32_t* messageID, uint32_t messageIDMask,
|
||||
uint8_t* data, uint8_t* dataSize,
|
||||
uint32_t* timeStamp, int32_t* status) {
|
||||
// Use a data size of 42 as call check. Difficult to add check to invoke
|
||||
void HAL_CAN_ReceiveMessage(int32_t busId, uint32_t messageId,
|
||||
struct HAL_CANReceiveMessage* message,
|
||||
int32_t* status) {
|
||||
// Use a data size of 100 as call check. Difficult to add check to invoke
|
||||
// handler
|
||||
*dataSize = 42;
|
||||
message->message.dataSize = 100;
|
||||
auto tmpStatus = *status;
|
||||
SimCanData->receiveMessage(messageID, messageIDMask, data, dataSize,
|
||||
timeStamp, status);
|
||||
SimCanData->receiveMessage(busId, messageId, message, status);
|
||||
// If no handler invoked, return message not found
|
||||
if (*dataSize == 42 && *status == tmpStatus) {
|
||||
if (message->message.dataSize == 100 && *status == tmpStatus) {
|
||||
*status = HAL_ERR_CANSessionMux_MessageNotFound;
|
||||
}
|
||||
}
|
||||
void HAL_CAN_OpenStreamSession(uint32_t* sessionHandle, uint32_t messageID,
|
||||
uint32_t messageIDMask, uint32_t maxMessages,
|
||||
int32_t* status) {
|
||||
SimCanData->openStreamSession(sessionHandle, messageID, messageIDMask,
|
||||
HAL_CANStreamHandle HAL_CAN_OpenStreamSession(int32_t busId, uint32_t messageId,
|
||||
uint32_t messageIDMask,
|
||||
uint32_t maxMessages,
|
||||
int32_t* status) {
|
||||
HAL_CANStreamHandle handle = 0;
|
||||
SimCanData->openStreamSession(&handle, busId, messageId, messageIDMask,
|
||||
maxMessages, status);
|
||||
return handle;
|
||||
}
|
||||
void HAL_CAN_CloseStreamSession(uint32_t sessionHandle) {
|
||||
void HAL_CAN_CloseStreamSession(HAL_CANStreamHandle sessionHandle) {
|
||||
SimCanData->closeStreamSession(sessionHandle);
|
||||
}
|
||||
void HAL_CAN_ReadStreamSession(uint32_t sessionHandle,
|
||||
void HAL_CAN_ReadStreamSession(HAL_CANStreamHandle sessionHandle,
|
||||
struct HAL_CANStreamMessage* messages,
|
||||
uint32_t messagesToRead, uint32_t* messagesRead,
|
||||
int32_t* status) {
|
||||
SimCanData->readStreamSession(sessionHandle, messages, messagesToRead,
|
||||
messagesRead, status);
|
||||
}
|
||||
void HAL_CAN_GetCANStatus(float* percentBusUtilization, uint32_t* busOffCount,
|
||||
uint32_t* txFullCount, uint32_t* receiveErrorCount,
|
||||
void HAL_CAN_GetCANStatus(int32_t busId, float* percentBusUtilization,
|
||||
uint32_t* busOffCount, uint32_t* txFullCount,
|
||||
uint32_t* receiveErrorCount,
|
||||
uint32_t* transmitErrorCount, int32_t* status) {
|
||||
SimCanData->getCANStatus(percentBusUtilization, busOffCount, txFullCount,
|
||||
receiveErrorCount, transmitErrorCount, status);
|
||||
SimCanData->getCANStatus(busId, percentBusUtilization, busOffCount,
|
||||
txFullCount, receiveErrorCount, transmitErrorCount,
|
||||
status);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -4,34 +4,31 @@
|
||||
|
||||
#include "hal/CANAPI.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <memory>
|
||||
|
||||
#include <wpi/DenseMap.h>
|
||||
#include <wpi/mutex.h>
|
||||
#include <wpi/timestamp.h>
|
||||
|
||||
#include "CANAPIInternal.h"
|
||||
#include "HALInitializer.h"
|
||||
#include "PortsInternal.h"
|
||||
#include "hal/CAN.h"
|
||||
#include "hal/Errors.h"
|
||||
#include "hal/HALBase.h"
|
||||
#include "hal/handles/UnlimitedHandleResource.h"
|
||||
|
||||
using namespace hal;
|
||||
|
||||
namespace {
|
||||
struct Receives {
|
||||
uint64_t lastTimeStamp;
|
||||
uint8_t data[8];
|
||||
uint8_t length;
|
||||
};
|
||||
|
||||
struct CANStorage {
|
||||
HAL_CANManufacturer manufacturer;
|
||||
HAL_CANDeviceType deviceType;
|
||||
int32_t busId;
|
||||
uint8_t deviceId;
|
||||
wpi::mutex periodicSendsMutex;
|
||||
wpi::SmallDenseMap<int32_t, int32_t> periodicSends;
|
||||
wpi::mutex receivesMutex;
|
||||
wpi::SmallDenseMap<int32_t, Receives> receives;
|
||||
wpi::SmallDenseMap<int32_t, HAL_CANReceiveMessage> receives;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@@ -66,18 +63,19 @@ static int32_t CreateCANId(CANStorage* storage, int32_t apiId) {
|
||||
createdId |= (storage->deviceId & 0x3F);
|
||||
return createdId;
|
||||
}
|
||||
extern "C" {
|
||||
uint32_t HAL_GetCANPacketBaseTime(void) {
|
||||
int status = 0;
|
||||
auto basetime = HAL_GetFPGATime(&status);
|
||||
// us to ms
|
||||
return (basetime / 1000ull) & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
HAL_CANHandle HAL_InitializeCAN(HAL_CANManufacturer manufacturer,
|
||||
extern "C" {
|
||||
|
||||
HAL_CANHandle HAL_InitializeCAN(int32_t busId, HAL_CANManufacturer manufacturer,
|
||||
int32_t deviceId, HAL_CANDeviceType deviceType,
|
||||
int32_t* status) {
|
||||
hal::init::CheckInit();
|
||||
|
||||
if (busId < 0 || busId > hal::kNumCanBuses) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return HAL_kInvalidHandle;
|
||||
}
|
||||
|
||||
auto can = std::make_shared<CANStorage>();
|
||||
|
||||
auto handle = canHandles->Allocate(can);
|
||||
@@ -87,6 +85,7 @@ HAL_CANHandle HAL_InitializeCAN(HAL_CANManufacturer manufacturer,
|
||||
return HAL_kInvalidHandle;
|
||||
}
|
||||
|
||||
can->busId = busId;
|
||||
can->deviceId = deviceId;
|
||||
can->deviceType = deviceType;
|
||||
can->manufacturer = manufacturer;
|
||||
@@ -105,13 +104,16 @@ void HAL_CleanCAN(HAL_CANHandle handle) {
|
||||
for (auto&& i : data->periodicSends) {
|
||||
int32_t s = 0;
|
||||
auto id = CreateCANId(data.get(), i.first);
|
||||
HAL_CAN_SendMessage(id, nullptr, 0, HAL_CAN_SEND_PERIOD_STOP_REPEATING, &s);
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
HAL_CAN_SendMessage(data->busId, id, &message,
|
||||
HAL_CAN_SEND_PERIOD_STOP_REPEATING, &s);
|
||||
i.second = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_WriteCANPacket(HAL_CANHandle handle, const uint8_t* data,
|
||||
int32_t length, int32_t apiId, int32_t* status) {
|
||||
void HAL_WriteCANPacket(HAL_CANHandle handle, int32_t apiId,
|
||||
const struct HAL_CANMessage* message, int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
@@ -120,12 +122,13 @@ void HAL_WriteCANPacket(HAL_CANHandle handle, const uint8_t* data,
|
||||
auto id = CreateCANId(can.get(), apiId);
|
||||
|
||||
std::scoped_lock lock(can->periodicSendsMutex);
|
||||
HAL_CAN_SendMessage(id, data, length, HAL_CAN_SEND_PERIOD_NO_REPEAT, status);
|
||||
HAL_CAN_SendMessage(can->busId, id, message, HAL_CAN_SEND_PERIOD_NO_REPEAT,
|
||||
status);
|
||||
can->periodicSends[apiId] = -1;
|
||||
}
|
||||
|
||||
void HAL_WriteCANPacketRepeating(HAL_CANHandle handle, const uint8_t* data,
|
||||
int32_t length, int32_t apiId,
|
||||
void HAL_WriteCANPacketRepeating(HAL_CANHandle handle, int32_t apiId,
|
||||
const struct HAL_CANMessage* message,
|
||||
int32_t repeatMs, int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
@@ -135,11 +138,12 @@ void HAL_WriteCANPacketRepeating(HAL_CANHandle handle, const uint8_t* data,
|
||||
auto id = CreateCANId(can.get(), apiId);
|
||||
|
||||
std::scoped_lock lock(can->periodicSendsMutex);
|
||||
HAL_CAN_SendMessage(id, data, length, repeatMs, status);
|
||||
HAL_CAN_SendMessage(can->busId, id, message, repeatMs, status);
|
||||
can->periodicSends[apiId] = repeatMs;
|
||||
}
|
||||
|
||||
void HAL_WriteCANRTRFrame(HAL_CANHandle handle, int32_t length, int32_t apiId,
|
||||
void HAL_WriteCANRTRFrame(HAL_CANHandle handle, int32_t apiId,
|
||||
const struct HAL_CANMessage* message,
|
||||
int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
@@ -148,11 +152,10 @@ void HAL_WriteCANRTRFrame(HAL_CANHandle handle, int32_t length, int32_t apiId,
|
||||
}
|
||||
auto id = CreateCANId(can.get(), apiId);
|
||||
id |= HAL_CAN_IS_FRAME_REMOTE;
|
||||
uint8_t data[8];
|
||||
std::memset(data, 0, sizeof(data));
|
||||
|
||||
std::scoped_lock lock(can->periodicSendsMutex);
|
||||
HAL_CAN_SendMessage(id, data, length, HAL_CAN_SEND_PERIOD_NO_REPEAT, status);
|
||||
HAL_CAN_SendMessage(can->busId, id, message, HAL_CAN_SEND_PERIOD_NO_REPEAT,
|
||||
status);
|
||||
can->periodicSends[apiId] = -1;
|
||||
}
|
||||
|
||||
@@ -165,14 +168,17 @@ void HAL_StopCANPacketRepeating(HAL_CANHandle handle, int32_t apiId,
|
||||
}
|
||||
auto id = CreateCANId(can.get(), apiId);
|
||||
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
|
||||
std::scoped_lock lock(can->periodicSendsMutex);
|
||||
HAL_CAN_SendMessage(id, nullptr, 0, HAL_CAN_SEND_PERIOD_STOP_REPEATING,
|
||||
status);
|
||||
HAL_CAN_SendMessage(can->busId, id, &message,
|
||||
HAL_CAN_SEND_PERIOD_STOP_REPEATING, status);
|
||||
can->periodicSends[apiId] = -1;
|
||||
}
|
||||
|
||||
void HAL_ReadCANPacketNew(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
|
||||
int32_t* length, uint64_t* receivedTimestamp,
|
||||
void HAL_ReadCANPacketNew(HAL_CANHandle handle, int32_t apiId,
|
||||
struct HAL_CANReceiveMessage* message,
|
||||
int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
@@ -181,24 +187,17 @@ void HAL_ReadCANPacketNew(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
|
||||
}
|
||||
|
||||
uint32_t messageId = CreateCANId(can.get(), apiId);
|
||||
uint8_t dataSize = 0;
|
||||
uint32_t ts = 0;
|
||||
HAL_CAN_ReceiveMessage(&messageId, 0x1FFFFFFF, data, &dataSize, &ts, status);
|
||||
|
||||
HAL_CAN_ReceiveMessage(can->busId, messageId, message, status);
|
||||
|
||||
if (*status == 0) {
|
||||
std::scoped_lock lock(can->receivesMutex);
|
||||
auto& msg = can->receives[messageId];
|
||||
msg.length = dataSize;
|
||||
msg.lastTimeStamp = ts;
|
||||
// The NetComm call placed in data, copy into the msg
|
||||
std::memcpy(msg.data, data, dataSize);
|
||||
can->receives[messageId] = *message;
|
||||
}
|
||||
*length = dataSize;
|
||||
*receivedTimestamp = ts;
|
||||
}
|
||||
|
||||
void HAL_ReadCANPacketLatest(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
|
||||
int32_t* length, uint64_t* receivedTimestamp,
|
||||
void HAL_ReadCANPacketLatest(HAL_CANHandle handle, int32_t apiId,
|
||||
struct HAL_CANReceiveMessage* message,
|
||||
int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
@@ -207,36 +206,26 @@ void HAL_ReadCANPacketLatest(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
|
||||
}
|
||||
|
||||
uint32_t messageId = CreateCANId(can.get(), apiId);
|
||||
uint8_t dataSize = 0;
|
||||
uint32_t ts = 0;
|
||||
HAL_CAN_ReceiveMessage(&messageId, 0x1FFFFFFF, data, &dataSize, &ts, status);
|
||||
|
||||
HAL_CAN_ReceiveMessage(can->busId, messageId, message, status);
|
||||
|
||||
std::scoped_lock lock(can->receivesMutex);
|
||||
if (*status == 0) {
|
||||
// fresh update
|
||||
auto& msg = can->receives[messageId];
|
||||
msg.length = dataSize;
|
||||
*length = dataSize;
|
||||
msg.lastTimeStamp = ts;
|
||||
*receivedTimestamp = ts;
|
||||
// The NetComm call placed in data, copy into the msg
|
||||
std::memcpy(msg.data, data, dataSize);
|
||||
can->receives[messageId] = *message;
|
||||
} else {
|
||||
auto i = can->receives.find(messageId);
|
||||
if (i != can->receives.end()) {
|
||||
// Read the data from the stored message into the output
|
||||
std::memcpy(data, i->second.data, i->second.length);
|
||||
*length = i->second.length;
|
||||
*receivedTimestamp = i->second.lastTimeStamp;
|
||||
*message = i->second;
|
||||
*status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_ReadCANPacketTimeout(HAL_CANHandle handle, int32_t apiId,
|
||||
uint8_t* data, int32_t* length,
|
||||
uint64_t* receivedTimestamp, int32_t timeoutMs,
|
||||
int32_t* status) {
|
||||
struct HAL_CANReceiveMessage* message,
|
||||
int32_t timeoutMs, int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
@@ -244,36 +233,43 @@ void HAL_ReadCANPacketTimeout(HAL_CANHandle handle, int32_t apiId,
|
||||
}
|
||||
|
||||
uint32_t messageId = CreateCANId(can.get(), apiId);
|
||||
uint8_t dataSize = 0;
|
||||
uint32_t ts = 0;
|
||||
HAL_CAN_ReceiveMessage(&messageId, 0x1FFFFFFF, data, &dataSize, &ts, status);
|
||||
|
||||
HAL_CAN_ReceiveMessage(can->busId, messageId, message, status);
|
||||
|
||||
std::scoped_lock lock(can->receivesMutex);
|
||||
if (*status == 0) {
|
||||
// fresh update
|
||||
auto& msg = can->receives[messageId];
|
||||
msg.length = dataSize;
|
||||
*length = dataSize;
|
||||
msg.lastTimeStamp = ts;
|
||||
*receivedTimestamp = ts;
|
||||
// The NetComm call placed in data, copy into the msg
|
||||
std::memcpy(msg.data, data, dataSize);
|
||||
can->receives[messageId] = *message;
|
||||
} else {
|
||||
auto i = can->receives.find(messageId);
|
||||
if (i != can->receives.end()) {
|
||||
// Found, check if new enough
|
||||
uint32_t now = HAL_GetCANPacketBaseTime();
|
||||
if (now - i->second.lastTimeStamp > static_cast<uint32_t>(timeoutMs)) {
|
||||
uint64_t now = wpi::Now();
|
||||
if (now - i->second.timeStamp >
|
||||
(static_cast<uint64_t>(timeoutMs) * 1000)) {
|
||||
// Timeout, return bad status
|
||||
*status = HAL_CAN_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
// Read the data from the stored message into the output
|
||||
std::memcpy(data, i->second.data, i->second.length);
|
||||
*length = i->second.length;
|
||||
*receivedTimestamp = i->second.lastTimeStamp;
|
||||
*message = i->second;
|
||||
*status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t HAL_StartCANStream(HAL_CANHandle handle, int32_t apiId, int32_t depth,
|
||||
int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t messageId = CreateCANId(can.get(), apiId);
|
||||
|
||||
uint32_t session = HAL_CAN_OpenStreamSession(can->busId, messageId,
|
||||
0x1FFFFFFF, depth, status);
|
||||
return session;
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
@@ -35,7 +35,7 @@ void InitializeCTREPCM() {
|
||||
}
|
||||
} // namespace hal::init
|
||||
|
||||
HAL_CTREPCMHandle HAL_InitializeCTREPCM(int32_t module,
|
||||
HAL_CTREPCMHandle HAL_InitializeCTREPCM(int32_t busId, int32_t module,
|
||||
const char* allocationLocation,
|
||||
int32_t* status) {
|
||||
hal::init::CheckInit();
|
||||
|
||||
@@ -13,6 +13,9 @@ void InitializePorts() {}
|
||||
} // namespace hal::init
|
||||
|
||||
extern "C" {
|
||||
int32_t HAL_GetNumCanBuses(void) {
|
||||
return kNumCanBuses;
|
||||
}
|
||||
int32_t HAL_GetNumAnalogInputs(void) {
|
||||
return kNumAnalogInputs;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
namespace hal {
|
||||
constexpr int32_t kNumCanBuses = 2;
|
||||
constexpr int32_t kAccelerometers = 1;
|
||||
constexpr int32_t kNumAccumulators = 2;
|
||||
constexpr int32_t kNumAnalogInputs = 8;
|
||||
|
||||
@@ -28,7 +28,7 @@ void InitializePowerDistribution() {}
|
||||
|
||||
extern "C" {
|
||||
HAL_PowerDistributionHandle HAL_InitializePowerDistribution(
|
||||
int32_t module, HAL_PowerDistributionType type,
|
||||
int32_t busId, int32_t module, HAL_PowerDistributionType type,
|
||||
const char* allocationLocation, int32_t* status) {
|
||||
if (type == HAL_PowerDistributionType_kAutomatic) {
|
||||
if (module != HAL_DEFAULT_POWER_DISTRIBUTION_MODULE) {
|
||||
@@ -56,7 +56,8 @@ HAL_PowerDistributionHandle HAL_InitializePowerDistribution(
|
||||
}
|
||||
hal::init::CheckInit();
|
||||
SimPowerDistributionData[module].initialized = true;
|
||||
auto handle = HAL_InitializeCAN(manufacturer, module, deviceType, status);
|
||||
auto handle =
|
||||
HAL_InitializeCAN(busId, manufacturer, module, deviceType, status);
|
||||
|
||||
if (*status != 0) {
|
||||
HAL_CleanCAN(handle);
|
||||
|
||||
@@ -35,7 +35,7 @@ void InitializeREVPH() {
|
||||
}
|
||||
} // namespace hal::init
|
||||
|
||||
HAL_REVPHHandle HAL_InitializeREVPH(int32_t module,
|
||||
HAL_REVPHHandle HAL_InitializeREVPH(int32_t busId, int32_t module,
|
||||
const char* allocationLocation,
|
||||
int32_t* status) {
|
||||
hal::init::CheckInit();
|
||||
|
||||
@@ -21,14 +21,13 @@
|
||||
#include <wpi/mutex.h>
|
||||
#include <wpi/timestamp.h>
|
||||
|
||||
#include "PortsInternal.h"
|
||||
#include "hal/Errors.h"
|
||||
#include "hal/Threads.h"
|
||||
#include "wpinet/EventLoopRunner.h"
|
||||
#include "wpinet/uv/Poll.h"
|
||||
#include "wpinet/uv/Timer.h"
|
||||
|
||||
#define NUM_CAN_BUSES 1
|
||||
|
||||
namespace {
|
||||
|
||||
static constexpr uint32_t MatchingBitMask = CAN_EFF_MASK | CAN_RTR_FLAG;
|
||||
@@ -68,20 +67,21 @@ struct FrameStore {
|
||||
struct SocketCanState {
|
||||
wpi::EventLoopRunner readLoopRunner;
|
||||
wpi::EventLoopRunner writeLoopRunner;
|
||||
wpi::mutex writeMutex[NUM_CAN_BUSES];
|
||||
int socketHandle[NUM_CAN_BUSES];
|
||||
wpi::mutex writeMutex[hal::kNumCanBuses];
|
||||
int socketHandle[hal::kNumCanBuses];
|
||||
// ms to count/timer map
|
||||
wpi::DenseMap<uint16_t, std::pair<size_t, std::weak_ptr<wpi::uv::Timer>>>
|
||||
timers;
|
||||
// ms to bus mask/packet
|
||||
wpi::DenseMap<uint16_t, std::array<std::optional<canfd_frame>, NUM_CAN_BUSES>>
|
||||
wpi::DenseMap<uint16_t,
|
||||
std::array<std::optional<canfd_frame>, hal::kNumCanBuses>>
|
||||
timedFrames;
|
||||
// packet to time
|
||||
wpi::DenseMap<uint32_t, std::array<uint16_t, NUM_CAN_BUSES>> packetToTime;
|
||||
wpi::DenseMap<uint32_t, std::array<uint16_t, hal::kNumCanBuses>> packetToTime;
|
||||
|
||||
wpi::mutex readMutex[NUM_CAN_BUSES];
|
||||
wpi::mutex readMutex[hal::kNumCanBuses];
|
||||
// TODO(thadhouse) we need a MUCH better way of doing this masking
|
||||
wpi::DenseMap<uint32_t, FrameStore> readFrames[NUM_CAN_BUSES];
|
||||
wpi::DenseMap<uint32_t, FrameStore> readFrames[hal::kNumCanBuses];
|
||||
|
||||
bool InitializeBuses();
|
||||
|
||||
@@ -111,7 +111,7 @@ bool SocketCanState::InitializeBuses() {
|
||||
std::printf("Failed to set CAN thread priority\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_CAN_BUSES; i++) {
|
||||
for (int i = 0; i < hal::kNumCanBuses; i++) {
|
||||
std::scoped_lock lock{writeMutex[i]};
|
||||
socketHandle[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
if (socketHandle[i] == -1) {
|
||||
@@ -240,23 +240,21 @@ namespace {} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
void HAL_CAN_SendMessage(uint32_t messageID, const uint8_t* data,
|
||||
uint8_t dataSize, int32_t periodMs, int32_t* status) {
|
||||
// TODO(thadhouse) this will become a parameter
|
||||
// isFd will also be a part of this parameter
|
||||
uint8_t busId = 0;
|
||||
|
||||
if (busId >= NUM_CAN_BUSES) {
|
||||
void HAL_CAN_SendMessage(int32_t busId, uint32_t messageId,
|
||||
const struct HAL_CANMessage* message, int32_t periodMs,
|
||||
int32_t* status) {
|
||||
if (busId < 0 || busId >= hal::kNumCanBuses) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
|
||||
bool isFd = false;
|
||||
messageID = MapMessageIdToSocketCan(messageID);
|
||||
messageId = MapMessageIdToSocketCan(messageId);
|
||||
|
||||
// TODO determine on the real roborio is a non periodic send removes any
|
||||
// periodic send.
|
||||
if (periodMs == HAL_CAN_SEND_PERIOD_STOP_REPEATING) {
|
||||
canState->writeLoopRunner.ExecSync([messageID, busId](wpi::uv::Loop&) {
|
||||
canState->RemovePeriodic(busId, messageID);
|
||||
canState->writeLoopRunner.ExecSync([messageId, busId](wpi::uv::Loop&) {
|
||||
canState->RemovePeriodic(busId, messageId);
|
||||
});
|
||||
|
||||
*status = 0;
|
||||
@@ -265,15 +263,20 @@ void HAL_CAN_SendMessage(uint32_t messageID, const uint8_t* data,
|
||||
|
||||
canfd_frame frame;
|
||||
std::memset(&frame, 0, sizeof(frame));
|
||||
frame.can_id = messageID;
|
||||
frame.flags = isFd ? CANFD_FDF | CANFD_BRS : 0;
|
||||
if (dataSize) {
|
||||
auto size = (std::min)(dataSize, static_cast<uint8_t>(sizeof(frame.data)));
|
||||
std::memcpy(frame.data, data, size);
|
||||
frame.can_id = messageId;
|
||||
frame.flags |=
|
||||
(message->flags & HAL_CANFlags::HAL_CAN_FD_DATALENGTH) ? CANFD_FDF : 0;
|
||||
frame.flags |=
|
||||
(message->flags & HAL_CANFlags::HAL_CAN_FD_BITRATESWITCH) ? CANFD_BRS : 0;
|
||||
if (message->dataSize) {
|
||||
auto size =
|
||||
(std::min)(message->dataSize, static_cast<uint8_t>(sizeof(frame.data)));
|
||||
std::memcpy(frame.data, message->data, size);
|
||||
frame.len = size;
|
||||
}
|
||||
|
||||
int mtu = isFd ? CANFD_MTU : CAN_MTU;
|
||||
int mtu = (message->flags & HAL_CANFlags::HAL_CAN_FD_DATALENGTH) ? CANFD_MTU
|
||||
: CAN_MTU;
|
||||
{
|
||||
std::scoped_lock lock{canState->writeMutex[busId]};
|
||||
int result = send(canState->socketHandle[busId], &frame, mtu, 0);
|
||||
@@ -291,70 +294,62 @@ void HAL_CAN_SendMessage(uint32_t messageID, const uint8_t* data,
|
||||
});
|
||||
}
|
||||
}
|
||||
void HAL_CAN_ReceiveMessage(uint32_t* messageID, uint32_t messageIDMask,
|
||||
uint8_t* data, uint8_t* dataSize,
|
||||
uint32_t* timeStamp, int32_t* status) {
|
||||
uint8_t busId = 0;
|
||||
|
||||
if (busId >= NUM_CAN_BUSES) {
|
||||
void HAL_CAN_ReceiveMessage(int32_t busId, uint32_t messageId,
|
||||
struct HAL_CANReceiveMessage* message,
|
||||
int32_t* status) {
|
||||
if (busId < 0 || busId >= hal::kNumCanBuses) {
|
||||
message->message.dataSize = 0;
|
||||
message->timeStamp = 0;
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
|
||||
std::scoped_lock lock{canState->readMutex[busId]};
|
||||
|
||||
// TODO(thadhouse) this is going to be wrong, but we're going to assume that
|
||||
// any lookup without the 11 bit mask set wants to look for a 29 bit frame.
|
||||
// Also, only do fast lookups for 29 bit frames
|
||||
|
||||
// Fast case is the following.
|
||||
// Mask doesn't include 11 bit flag
|
||||
// Mask doesn't include RTR flag
|
||||
// Mask is full
|
||||
if (messageIDMask == CAN_EFF_MASK) {
|
||||
// We're doing a fast lookup
|
||||
auto& msg = canState->readFrames[busId][*messageID];
|
||||
if (msg.timestamp == 0) {
|
||||
*status = HAL_ERR_CANSessionMux_MessageNotFound;
|
||||
return;
|
||||
}
|
||||
if ((msg.frame.flags & CANFD_FDF) || msg.frame.len > 8) {
|
||||
std::printf("FD frames not supported for read right now\n");
|
||||
*status = HAL_ERR_CANSessionMux_InvalidBuffer;
|
||||
return;
|
||||
}
|
||||
// TODO(thadhouse) this time needs to be fixed up.
|
||||
*timeStamp = msg.timestamp / 1000;
|
||||
std::memcpy(data, msg.frame.data, msg.frame.len);
|
||||
*dataSize = msg.frame.len;
|
||||
*status = 0;
|
||||
msg.timestamp = 0;
|
||||
auto& msg = canState->readFrames[busId][messageId];
|
||||
if (msg.timestamp == 0) {
|
||||
message->message.dataSize = 0;
|
||||
message->timeStamp = 0;
|
||||
*status = HAL_ERR_CANSessionMux_MessageNotFound;
|
||||
return;
|
||||
}
|
||||
|
||||
std::printf("Slow lookup not supported yet\n");
|
||||
message->message.flags = HAL_CANFlags::HAL_CAN_NO_FLAGS;
|
||||
message->message.flags |= (msg.frame.flags & CANFD_FDF)
|
||||
? HAL_CANFlags::HAL_CAN_FD_DATALENGTH
|
||||
: HAL_CANFlags::HAL_CAN_NO_FLAGS;
|
||||
message->message.flags |= (msg.frame.flags & CANFD_BRS)
|
||||
? HAL_CANFlags::HAL_CAN_FD_BITRATESWITCH
|
||||
: HAL_CANFlags::HAL_CAN_NO_FLAGS;
|
||||
|
||||
// Add support for slow lookup later
|
||||
*status = HAL_ERR_CANSessionMux_NotAllowed;
|
||||
message->message.dataSize = msg.frame.len;
|
||||
if (msg.frame.len > 0) {
|
||||
std::memcpy(message->message.data, msg.frame.data, msg.frame.len);
|
||||
}
|
||||
|
||||
message->timeStamp = msg.timestamp;
|
||||
*status = 0;
|
||||
msg.timestamp = 0;
|
||||
return;
|
||||
}
|
||||
void HAL_CAN_OpenStreamSession(uint32_t* sessionHandle, uint32_t messageID,
|
||||
uint32_t messageIDMask, uint32_t maxMessages,
|
||||
int32_t* status) {
|
||||
*sessionHandle = 0;
|
||||
HAL_CANStreamHandle HAL_CAN_OpenStreamSession(int32_t busId, uint32_t messageId,
|
||||
uint32_t messageIDMask,
|
||||
uint32_t maxMessages,
|
||||
int32_t* status) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
void HAL_CAN_CloseStreamSession(uint32_t sessionHandle) {}
|
||||
void HAL_CAN_ReadStreamSession(uint32_t sessionHandle,
|
||||
void HAL_CAN_CloseStreamSession(HAL_CANStreamHandle sessionHandle) {}
|
||||
void HAL_CAN_ReadStreamSession(HAL_CANStreamHandle sessionHandle,
|
||||
struct HAL_CANStreamMessage* messages,
|
||||
uint32_t messagesToRead, uint32_t* messagesRead,
|
||||
int32_t* status) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
void HAL_CAN_GetCANStatus(float* percentBusUtilization, uint32_t* busOffCount,
|
||||
uint32_t* txFullCount, uint32_t* receiveErrorCount,
|
||||
void HAL_CAN_GetCANStatus(int32_t busId, float* percentBusUtilization,
|
||||
uint32_t* busOffCount, uint32_t* txFullCount,
|
||||
uint32_t* receiveErrorCount,
|
||||
uint32_t* transmitErrorCount, int32_t* status) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <wpi/timestamp.h>
|
||||
|
||||
#include "HALInitializer.h"
|
||||
#include "PortsInternal.h"
|
||||
#include "hal/CAN.h"
|
||||
#include "hal/Errors.h"
|
||||
#include "hal/handles/UnlimitedHandleResource.h"
|
||||
@@ -19,20 +20,15 @@
|
||||
using namespace hal;
|
||||
|
||||
namespace {
|
||||
struct Receives {
|
||||
uint32_t lastTimeStamp;
|
||||
uint8_t data[8];
|
||||
uint8_t length;
|
||||
};
|
||||
|
||||
struct CANStorage {
|
||||
HAL_CANManufacturer manufacturer;
|
||||
HAL_CANDeviceType deviceType;
|
||||
int32_t busId;
|
||||
uint8_t deviceId;
|
||||
wpi::mutex periodicSendsMutex;
|
||||
wpi::SmallDenseMap<int32_t, int32_t> periodicSends;
|
||||
wpi::mutex receivesMutex;
|
||||
wpi::SmallDenseMap<int32_t, Receives> receives;
|
||||
wpi::SmallDenseMap<int32_t, HAL_CANReceiveMessage> receives;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@@ -58,14 +54,16 @@ static int32_t CreateCANId(CANStorage* storage, int32_t apiId) {
|
||||
|
||||
extern "C" {
|
||||
|
||||
uint32_t HAL_GetCANPacketBaseTime(void) {
|
||||
return wpi::Now() / 1000;
|
||||
}
|
||||
|
||||
HAL_CANHandle HAL_InitializeCAN(HAL_CANManufacturer manufacturer,
|
||||
HAL_CANHandle HAL_InitializeCAN(int32_t busId, HAL_CANManufacturer manufacturer,
|
||||
int32_t deviceId, HAL_CANDeviceType deviceType,
|
||||
int32_t* status) {
|
||||
hal::init::CheckInit();
|
||||
|
||||
if (busId < 0 || busId > hal::kNumCanBuses) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return HAL_kInvalidHandle;
|
||||
}
|
||||
|
||||
auto can = std::make_shared<CANStorage>();
|
||||
|
||||
auto handle = canHandles->Allocate(can);
|
||||
@@ -75,6 +73,7 @@ HAL_CANHandle HAL_InitializeCAN(HAL_CANManufacturer manufacturer,
|
||||
return HAL_kInvalidHandle;
|
||||
}
|
||||
|
||||
can->busId = busId;
|
||||
can->deviceId = deviceId;
|
||||
can->deviceType = deviceType;
|
||||
can->manufacturer = manufacturer;
|
||||
@@ -93,13 +92,16 @@ void HAL_CleanCAN(HAL_CANHandle handle) {
|
||||
for (auto&& i : data->periodicSends) {
|
||||
int32_t s = 0;
|
||||
auto id = CreateCANId(data.get(), i.first);
|
||||
HAL_CAN_SendMessage(id, nullptr, 0, HAL_CAN_SEND_PERIOD_STOP_REPEATING, &s);
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
HAL_CAN_SendMessage(data->busId, id, &message,
|
||||
HAL_CAN_SEND_PERIOD_STOP_REPEATING, &s);
|
||||
i.second = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_WriteCANPacket(HAL_CANHandle handle, const uint8_t* data,
|
||||
int32_t length, int32_t apiId, int32_t* status) {
|
||||
void HAL_WriteCANPacket(HAL_CANHandle handle, int32_t apiId,
|
||||
const struct HAL_CANMessage* message, int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
@@ -108,12 +110,13 @@ void HAL_WriteCANPacket(HAL_CANHandle handle, const uint8_t* data,
|
||||
auto id = CreateCANId(can.get(), apiId);
|
||||
|
||||
std::scoped_lock lock(can->periodicSendsMutex);
|
||||
HAL_CAN_SendMessage(id, data, length, HAL_CAN_SEND_PERIOD_NO_REPEAT, status);
|
||||
HAL_CAN_SendMessage(can->busId, id, message, HAL_CAN_SEND_PERIOD_NO_REPEAT,
|
||||
status);
|
||||
can->periodicSends[apiId] = -1;
|
||||
}
|
||||
|
||||
void HAL_WriteCANPacketRepeating(HAL_CANHandle handle, const uint8_t* data,
|
||||
int32_t length, int32_t apiId,
|
||||
void HAL_WriteCANPacketRepeating(HAL_CANHandle handle, int32_t apiId,
|
||||
const struct HAL_CANMessage* message,
|
||||
int32_t repeatMs, int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
@@ -123,11 +126,12 @@ void HAL_WriteCANPacketRepeating(HAL_CANHandle handle, const uint8_t* data,
|
||||
auto id = CreateCANId(can.get(), apiId);
|
||||
|
||||
std::scoped_lock lock(can->periodicSendsMutex);
|
||||
HAL_CAN_SendMessage(id, data, length, repeatMs, status);
|
||||
HAL_CAN_SendMessage(can->busId, id, message, repeatMs, status);
|
||||
can->periodicSends[apiId] = repeatMs;
|
||||
}
|
||||
|
||||
void HAL_WriteCANRTRFrame(HAL_CANHandle handle, int32_t length, int32_t apiId,
|
||||
void HAL_WriteCANRTRFrame(HAL_CANHandle handle, int32_t apiId,
|
||||
const struct HAL_CANMessage* message,
|
||||
int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
@@ -136,11 +140,10 @@ void HAL_WriteCANRTRFrame(HAL_CANHandle handle, int32_t length, int32_t apiId,
|
||||
}
|
||||
auto id = CreateCANId(can.get(), apiId);
|
||||
id |= HAL_CAN_IS_FRAME_REMOTE;
|
||||
uint8_t data[8];
|
||||
std::memset(data, 0, sizeof(data));
|
||||
|
||||
std::scoped_lock lock(can->periodicSendsMutex);
|
||||
HAL_CAN_SendMessage(id, data, length, HAL_CAN_SEND_PERIOD_NO_REPEAT, status);
|
||||
HAL_CAN_SendMessage(can->busId, id, message, HAL_CAN_SEND_PERIOD_NO_REPEAT,
|
||||
status);
|
||||
can->periodicSends[apiId] = -1;
|
||||
}
|
||||
|
||||
@@ -153,14 +156,17 @@ void HAL_StopCANPacketRepeating(HAL_CANHandle handle, int32_t apiId,
|
||||
}
|
||||
auto id = CreateCANId(can.get(), apiId);
|
||||
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
|
||||
std::scoped_lock lock(can->periodicSendsMutex);
|
||||
HAL_CAN_SendMessage(id, nullptr, 0, HAL_CAN_SEND_PERIOD_STOP_REPEATING,
|
||||
status);
|
||||
HAL_CAN_SendMessage(can->busId, id, &message,
|
||||
HAL_CAN_SEND_PERIOD_STOP_REPEATING, status);
|
||||
can->periodicSends[apiId] = -1;
|
||||
}
|
||||
|
||||
void HAL_ReadCANPacketNew(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
|
||||
int32_t* length, uint64_t* receivedTimestamp,
|
||||
void HAL_ReadCANPacketNew(HAL_CANHandle handle, int32_t apiId,
|
||||
struct HAL_CANReceiveMessage* message,
|
||||
int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
@@ -169,24 +175,17 @@ void HAL_ReadCANPacketNew(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
|
||||
}
|
||||
|
||||
uint32_t messageId = CreateCANId(can.get(), apiId);
|
||||
uint8_t dataSize = 0;
|
||||
uint32_t ts = 0;
|
||||
HAL_CAN_ReceiveMessage(&messageId, 0x1FFFFFFF, data, &dataSize, &ts, status);
|
||||
|
||||
HAL_CAN_ReceiveMessage(can->busId, messageId, message, status);
|
||||
|
||||
if (*status == 0) {
|
||||
std::scoped_lock lock(can->receivesMutex);
|
||||
auto& msg = can->receives[messageId];
|
||||
msg.length = dataSize;
|
||||
msg.lastTimeStamp = ts;
|
||||
// The NetComm call placed in data, copy into the msg
|
||||
std::memcpy(msg.data, data, dataSize);
|
||||
can->receives[messageId] = *message;
|
||||
}
|
||||
*length = dataSize;
|
||||
*receivedTimestamp = ts;
|
||||
}
|
||||
|
||||
void HAL_ReadCANPacketLatest(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
|
||||
int32_t* length, uint64_t* receivedTimestamp,
|
||||
void HAL_ReadCANPacketLatest(HAL_CANHandle handle, int32_t apiId,
|
||||
struct HAL_CANReceiveMessage* message,
|
||||
int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
@@ -195,36 +194,26 @@ void HAL_ReadCANPacketLatest(HAL_CANHandle handle, int32_t apiId, uint8_t* data,
|
||||
}
|
||||
|
||||
uint32_t messageId = CreateCANId(can.get(), apiId);
|
||||
uint8_t dataSize = 0;
|
||||
uint32_t ts = 0;
|
||||
HAL_CAN_ReceiveMessage(&messageId, 0x1FFFFFFF, data, &dataSize, &ts, status);
|
||||
|
||||
HAL_CAN_ReceiveMessage(can->busId, messageId, message, status);
|
||||
|
||||
std::scoped_lock lock(can->receivesMutex);
|
||||
if (*status == 0) {
|
||||
// fresh update
|
||||
auto& msg = can->receives[messageId];
|
||||
msg.length = dataSize;
|
||||
*length = dataSize;
|
||||
msg.lastTimeStamp = ts;
|
||||
*receivedTimestamp = ts;
|
||||
// The NetComm call placed in data, copy into the msg
|
||||
std::memcpy(msg.data, data, dataSize);
|
||||
can->receives[messageId] = *message;
|
||||
} else {
|
||||
auto i = can->receives.find(messageId);
|
||||
if (i != can->receives.end()) {
|
||||
// Read the data from the stored message into the output
|
||||
std::memcpy(data, i->second.data, i->second.length);
|
||||
*length = i->second.length;
|
||||
*receivedTimestamp = i->second.lastTimeStamp;
|
||||
*message = i->second;
|
||||
*status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_ReadCANPacketTimeout(HAL_CANHandle handle, int32_t apiId,
|
||||
uint8_t* data, int32_t* length,
|
||||
uint64_t* receivedTimestamp, int32_t timeoutMs,
|
||||
int32_t* status) {
|
||||
struct HAL_CANReceiveMessage* message,
|
||||
int32_t timeoutMs, int32_t* status) {
|
||||
auto can = canHandles->Get(handle);
|
||||
if (!can) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
@@ -232,34 +221,26 @@ void HAL_ReadCANPacketTimeout(HAL_CANHandle handle, int32_t apiId,
|
||||
}
|
||||
|
||||
uint32_t messageId = CreateCANId(can.get(), apiId);
|
||||
uint8_t dataSize = 0;
|
||||
uint32_t ts = 0;
|
||||
HAL_CAN_ReceiveMessage(&messageId, 0x1FFFFFFF, data, &dataSize, &ts, status);
|
||||
|
||||
HAL_CAN_ReceiveMessage(can->busId, messageId, message, status);
|
||||
|
||||
std::scoped_lock lock(can->receivesMutex);
|
||||
if (*status == 0) {
|
||||
// fresh update
|
||||
auto& msg = can->receives[messageId];
|
||||
msg.length = dataSize;
|
||||
*length = dataSize;
|
||||
msg.lastTimeStamp = ts;
|
||||
*receivedTimestamp = ts;
|
||||
// The NetComm call placed in data, copy into the msg
|
||||
std::memcpy(msg.data, data, dataSize);
|
||||
can->receives[messageId] = *message;
|
||||
} else {
|
||||
auto i = can->receives.find(messageId);
|
||||
if (i != can->receives.end()) {
|
||||
// Found, check if new enough
|
||||
uint32_t now = HAL_GetCANPacketBaseTime();
|
||||
if (now - i->second.lastTimeStamp > static_cast<uint32_t>(timeoutMs)) {
|
||||
uint64_t now = wpi::Now();
|
||||
if (now - i->second.timeStamp >
|
||||
(static_cast<uint64_t>(timeoutMs) * 1000)) {
|
||||
// Timeout, return bad status
|
||||
*status = HAL_CAN_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
// Read the data from the stored message into the output
|
||||
std::memcpy(data, i->second.data, i->second.length);
|
||||
*length = i->second.length;
|
||||
*receivedTimestamp = i->second.lastTimeStamp;
|
||||
*message = i->second;
|
||||
*status = 0;
|
||||
}
|
||||
}
|
||||
@@ -275,8 +256,8 @@ uint32_t HAL_StartCANStream(HAL_CANHandle handle, int32_t apiId, int32_t depth,
|
||||
|
||||
uint32_t messageId = CreateCANId(can.get(), apiId);
|
||||
|
||||
uint32_t session = 0;
|
||||
HAL_CAN_OpenStreamSession(&session, messageId, 0x1FFFFFFF, depth, status);
|
||||
uint32_t session = HAL_CAN_OpenStreamSession(can->busId, messageId,
|
||||
0x1FFFFFFF, depth, status);
|
||||
return session;
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
@@ -145,33 +145,37 @@ void InitializeCTREPCM() {
|
||||
}
|
||||
} // namespace hal::init
|
||||
|
||||
#define READ_PACKET(type, frame, failureValue) \
|
||||
auto pcm = pcmHandles->Get(handle); \
|
||||
if (pcm == nullptr) { \
|
||||
*status = HAL_HANDLE_ERROR; \
|
||||
return failureValue; \
|
||||
} \
|
||||
type pcmStatus; \
|
||||
int32_t length = 0; \
|
||||
uint64_t receivedTimestamp = 0; \
|
||||
HAL_ReadCANPacketTimeout(pcm->canHandle, frame, pcmStatus.data, &length, \
|
||||
&receivedTimestamp, TimeoutMs, status); \
|
||||
if (*status != 0) { \
|
||||
return failureValue; \
|
||||
}
|
||||
#define READ_PACKET(type, frame, failureValue) \
|
||||
auto pcm = pcmHandles->Get(handle); \
|
||||
if (pcm == nullptr) { \
|
||||
*status = HAL_HANDLE_ERROR; \
|
||||
return failureValue; \
|
||||
} \
|
||||
HAL_CANReceiveMessage message; \
|
||||
type pcmStatus; \
|
||||
HAL_ReadCANPacketTimeout(pcm->canHandle, frame, &message, TimeoutMs, \
|
||||
status); \
|
||||
if (*status != 0) { \
|
||||
return failureValue; \
|
||||
} \
|
||||
std::memcpy(pcmStatus.data, message.message.data, sizeof(pcmStatus.data));
|
||||
|
||||
#define READ_STATUS(failureValue) READ_PACKET(PcmStatus, Status1, failureValue)
|
||||
#define READ_SOL_FAULTS(failureValue) \
|
||||
READ_PACKET(PcmStatusFault, StatusSolFaults, failureValue)
|
||||
|
||||
static void SendControl(PCM* pcm, int32_t* status) {
|
||||
HAL_WriteCANPacketRepeating(pcm->canHandle, pcm->control.data, 8, Control1,
|
||||
SendPeriod, status);
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.dataSize = 8;
|
||||
std::memcpy(message.data, pcm->control.data, 8);
|
||||
HAL_WriteCANPacketRepeating(pcm->canHandle, Control1, &message, SendPeriod,
|
||||
status);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
HAL_CTREPCMHandle HAL_InitializeCTREPCM(int32_t module,
|
||||
HAL_CTREPCMHandle HAL_InitializeCTREPCM(int32_t busId, int32_t module,
|
||||
const char* allocationLocation,
|
||||
int32_t* status) {
|
||||
hal::init::CheckInit();
|
||||
@@ -190,7 +194,8 @@ HAL_CTREPCMHandle HAL_InitializeCTREPCM(int32_t module,
|
||||
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
|
||||
}
|
||||
|
||||
pcm->canHandle = HAL_InitializeCAN(manufacturer, module, deviceType, status);
|
||||
pcm->canHandle =
|
||||
HAL_InitializeCAN(busId, manufacturer, module, deviceType, status);
|
||||
if (*status != 0) {
|
||||
pcmHandles->Free(handle);
|
||||
return HAL_kInvalidHandle;
|
||||
@@ -344,9 +349,11 @@ void HAL_ClearAllCTREPCMStickyFaults(HAL_CTREPCMHandle handle,
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
uint8_t controlData[] = {0, 0, 0, 0x80};
|
||||
HAL_WriteCANPacket(pcm->canHandle, controlData, sizeof(controlData), Control2,
|
||||
status);
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.dataSize = 4;
|
||||
message.data[3] = 0x80;
|
||||
HAL_WriteCANPacket(pcm->canHandle, Control2, &message, status);
|
||||
}
|
||||
|
||||
void HAL_FireCTREPCMOneShot(HAL_CTREPCMHandle handle, int32_t index,
|
||||
@@ -397,11 +404,16 @@ void HAL_SetCTREPCMOneShotDuration(HAL_CTREPCMHandle handle, int32_t index,
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.dataSize = 8;
|
||||
|
||||
std::scoped_lock lock{pcm->lock};
|
||||
pcm->oneShot.sol10MsPerUnit[index] = (std::min)(
|
||||
static_cast<uint32_t>(durMs) / 10, static_cast<uint32_t>(0xFF));
|
||||
HAL_WriteCANPacketRepeating(pcm->canHandle, pcm->oneShot.sol10MsPerUnit, 8,
|
||||
Control3, SendPeriod, status);
|
||||
std::memcpy(message.data, pcm->oneShot.sol10MsPerUnit, 8);
|
||||
HAL_WriteCANPacketRepeating(pcm->canHandle, Control3, &message, SendPeriod,
|
||||
status);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -129,7 +129,8 @@ void InitializeCTREPDP() {
|
||||
|
||||
extern "C" {
|
||||
|
||||
HAL_PDPHandle HAL_InitializePDP(int32_t module, const char* allocationLocation,
|
||||
HAL_PDPHandle HAL_InitializePDP(int32_t busId, int32_t module,
|
||||
const char* allocationLocation,
|
||||
int32_t* status) {
|
||||
hal::init::CheckInit();
|
||||
if (!HAL_CheckPDPModule(module)) {
|
||||
@@ -153,7 +154,8 @@ HAL_PDPHandle HAL_InitializePDP(int32_t module, const char* allocationLocation,
|
||||
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
|
||||
}
|
||||
|
||||
pdp->canHandle = HAL_InitializeCAN(manufacturer, module, deviceType, status);
|
||||
pdp->canHandle =
|
||||
HAL_InitializeCAN(busId, manufacturer, module, deviceType, status);
|
||||
if (*status != 0) {
|
||||
pdpHandles->Free(handle);
|
||||
return HAL_kInvalidHandle;
|
||||
@@ -191,16 +193,16 @@ double HAL_GetPDPTemperature(HAL_PDPHandle handle, int32_t* status) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HAL_CANReceiveMessage message;
|
||||
PdpStatus3 pdpStatus;
|
||||
int32_t length = 0;
|
||||
uint64_t receivedTimestamp = 0;
|
||||
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status3, pdpStatus.data, &length,
|
||||
&receivedTimestamp, TimeoutMs, status);
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status3, &message, TimeoutMs,
|
||||
status);
|
||||
|
||||
if (*status != 0) {
|
||||
return 0;
|
||||
} else {
|
||||
std::memcpy(pdpStatus.data, message.message.data, sizeof(pdpStatus.data));
|
||||
return pdpStatus.bits.temp * 1.03250836957542 - 67.8564500484966;
|
||||
}
|
||||
}
|
||||
@@ -212,16 +214,16 @@ double HAL_GetPDPVoltage(HAL_PDPHandle handle, int32_t* status) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HAL_CANReceiveMessage message;
|
||||
PdpStatus3 pdpStatus;
|
||||
int32_t length = 0;
|
||||
uint64_t receivedTimestamp = 0;
|
||||
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status3, pdpStatus.data, &length,
|
||||
&receivedTimestamp, TimeoutMs, status);
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status3, &message, TimeoutMs,
|
||||
status);
|
||||
|
||||
if (*status != 0) {
|
||||
return 0;
|
||||
} else {
|
||||
std::memcpy(pdpStatus.data, message.message.data, sizeof(pdpStatus.data));
|
||||
return pdpStatus.bits.busVoltage * 0.05 + 4.0; /* 50mV per unit plus 4V. */
|
||||
}
|
||||
}
|
||||
@@ -240,18 +242,18 @@ double HAL_GetPDPChannelCurrent(HAL_PDPHandle handle, int32_t channel,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t length = 0;
|
||||
uint64_t receivedTimestamp = 0;
|
||||
HAL_CANReceiveMessage message;
|
||||
|
||||
double raw = 0;
|
||||
|
||||
if (channel <= 5) {
|
||||
PdpStatus1 pdpStatus;
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status1, pdpStatus.data, &length,
|
||||
&receivedTimestamp, TimeoutMs, status);
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status1, &message, TimeoutMs,
|
||||
status);
|
||||
if (*status != 0) {
|
||||
return 0;
|
||||
}
|
||||
std::memcpy(pdpStatus.data, message.message.data, sizeof(pdpStatus.data));
|
||||
switch (channel) {
|
||||
case 0:
|
||||
raw = (static_cast<uint32_t>(pdpStatus.bits.chan1_h8) << 2) |
|
||||
@@ -280,11 +282,12 @@ double HAL_GetPDPChannelCurrent(HAL_PDPHandle handle, int32_t channel,
|
||||
}
|
||||
} else if (channel <= 11) {
|
||||
PdpStatus2 pdpStatus;
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status2, pdpStatus.data, &length,
|
||||
&receivedTimestamp, TimeoutMs, status);
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status2, &message, TimeoutMs,
|
||||
status);
|
||||
if (*status != 0) {
|
||||
return 0;
|
||||
}
|
||||
std::memcpy(pdpStatus.data, message.message.data, sizeof(pdpStatus.data));
|
||||
switch (channel) {
|
||||
case 6:
|
||||
raw = (static_cast<uint32_t>(pdpStatus.bits.chan7_h8) << 2) |
|
||||
@@ -313,11 +316,12 @@ double HAL_GetPDPChannelCurrent(HAL_PDPHandle handle, int32_t channel,
|
||||
}
|
||||
} else {
|
||||
PdpStatus3 pdpStatus;
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status3, pdpStatus.data, &length,
|
||||
&receivedTimestamp, TimeoutMs, status);
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status3, &message, TimeoutMs,
|
||||
status);
|
||||
if (*status != 0) {
|
||||
return 0;
|
||||
}
|
||||
std::memcpy(pdpStatus.data, message.message.data, sizeof(pdpStatus.data));
|
||||
switch (channel) {
|
||||
case 12:
|
||||
raw = (static_cast<uint32_t>(pdpStatus.bits.chan13_h8) << 2) |
|
||||
@@ -350,26 +354,28 @@ void HAL_GetPDPAllChannelCurrents(HAL_PDPHandle handle, double* currents,
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t length = 0;
|
||||
uint64_t receivedTimestamp = 0;
|
||||
HAL_CANReceiveMessage message;
|
||||
PdpStatus1 pdpStatus;
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status1, pdpStatus.data, &length,
|
||||
&receivedTimestamp, TimeoutMs, status);
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status1, &message, TimeoutMs,
|
||||
status);
|
||||
if (*status != 0) {
|
||||
return;
|
||||
}
|
||||
std::memcpy(pdpStatus.data, message.message.data, sizeof(pdpStatus.data));
|
||||
PdpStatus2 pdpStatus2;
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status2, pdpStatus2.data, &length,
|
||||
&receivedTimestamp, TimeoutMs, status);
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status2, &message, TimeoutMs,
|
||||
status);
|
||||
if (*status != 0) {
|
||||
return;
|
||||
}
|
||||
std::memcpy(pdpStatus2.data, message.message.data, sizeof(pdpStatus2.data));
|
||||
PdpStatus3 pdpStatus3;
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status3, pdpStatus3.data, &length,
|
||||
&receivedTimestamp, TimeoutMs, status);
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, Status3, &message, TimeoutMs,
|
||||
status);
|
||||
if (*status != 0) {
|
||||
return;
|
||||
}
|
||||
std::memcpy(pdpStatus3.data, message.message.data, sizeof(pdpStatus3.data));
|
||||
|
||||
currents[0] = ((static_cast<uint32_t>(pdpStatus.bits.chan1_h8) << 2) |
|
||||
pdpStatus.bits.chan1_l2) *
|
||||
@@ -430,15 +436,15 @@ double HAL_GetPDPTotalCurrent(HAL_PDPHandle handle, int32_t* status) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HAL_CANReceiveMessage message;
|
||||
PdpStatusEnergy pdpStatus;
|
||||
int32_t length = 0;
|
||||
uint64_t receivedTimestamp = 0;
|
||||
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, StatusEnergy, pdpStatus.data,
|
||||
&length, &receivedTimestamp, TimeoutMs, status);
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, StatusEnergy, &message, TimeoutMs,
|
||||
status);
|
||||
if (*status != 0) {
|
||||
return 0;
|
||||
}
|
||||
std::memcpy(pdpStatus.data, message.message.data, sizeof(pdpStatus.data));
|
||||
|
||||
uint32_t raw;
|
||||
raw = pdpStatus.bits.TotalCurrent_125mAperunit_h8;
|
||||
@@ -454,15 +460,15 @@ double HAL_GetPDPTotalPower(HAL_PDPHandle handle, int32_t* status) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HAL_CANReceiveMessage message;
|
||||
PdpStatusEnergy pdpStatus;
|
||||
int32_t length = 0;
|
||||
uint64_t receivedTimestamp = 0;
|
||||
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, StatusEnergy, pdpStatus.data,
|
||||
&length, &receivedTimestamp, TimeoutMs, status);
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, StatusEnergy, &message, TimeoutMs,
|
||||
status);
|
||||
if (*status != 0) {
|
||||
return 0;
|
||||
}
|
||||
std::memcpy(pdpStatus.data, message.message.data, sizeof(pdpStatus.data));
|
||||
|
||||
uint32_t raw;
|
||||
raw = pdpStatus.bits.Power_125mWperunit_h4;
|
||||
@@ -480,15 +486,15 @@ double HAL_GetPDPTotalEnergy(HAL_PDPHandle handle, int32_t* status) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HAL_CANReceiveMessage message;
|
||||
PdpStatusEnergy pdpStatus;
|
||||
int32_t length = 0;
|
||||
uint64_t receivedTimestamp = 0;
|
||||
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, StatusEnergy, pdpStatus.data,
|
||||
&length, &receivedTimestamp, TimeoutMs, status);
|
||||
HAL_ReadCANPacketTimeout(pdp->canHandle, StatusEnergy, &message, TimeoutMs,
|
||||
status);
|
||||
if (*status != 0) {
|
||||
return 0;
|
||||
}
|
||||
std::memcpy(pdpStatus.data, message.message.data, sizeof(pdpStatus.data));
|
||||
|
||||
uint32_t raw;
|
||||
raw = pdpStatus.bits.Energy_125mWPerUnitXTmeas_h4;
|
||||
@@ -514,8 +520,12 @@ void HAL_ResetPDPTotalEnergy(HAL_PDPHandle handle, int32_t* status) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t pdpControl[] = {0x40}; /* only bit set is ResetEnergy */
|
||||
HAL_WriteCANPacket(pdp->canHandle, pdpControl, 1, Control1, status);
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.dataSize = 1;
|
||||
message.data[0] = 0x40; /* only bit set is ResetEnergy */
|
||||
|
||||
HAL_WriteCANPacket(pdp->canHandle, Control1, &message, status);
|
||||
}
|
||||
|
||||
void HAL_ClearPDPStickyFaults(HAL_PDPHandle handle, int32_t* status) {
|
||||
@@ -525,8 +535,12 @@ void HAL_ClearPDPStickyFaults(HAL_PDPHandle handle, int32_t* status) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t pdpControl[] = {0x80}; /* only bit set is ClearStickyFaults */
|
||||
HAL_WriteCANPacket(pdp->canHandle, pdpControl, 1, Control1, status);
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.dataSize = 1;
|
||||
message.data[0] = 0x80; /* only bit set is ClearStickyFaults */
|
||||
|
||||
HAL_WriteCANPacket(pdp->canHandle, Control1, &message, status);
|
||||
}
|
||||
|
||||
uint32_t HAL_StartCANStream(HAL_CANHandle handle, int32_t apiId, int32_t depth,
|
||||
@@ -594,8 +608,9 @@ HAL_PowerDistributionChannelData* HAL_GetPDPStreamData(HAL_PDPHandle handle,
|
||||
|
||||
for (uint32_t i = 0; i < messagesRead; i++) {
|
||||
PdpStatus1 pdpStatus;
|
||||
std::memcpy(pdpStatus.data, messages[i].data, sizeof(messages[i].data));
|
||||
uint32_t timestamp = messages[i].timeStamp;
|
||||
std::memcpy(pdpStatus.data, messages[i].message.message.data,
|
||||
sizeof(pdpStatus));
|
||||
uint64_t timestamp = messages[i].message.timeStamp;
|
||||
|
||||
retData[*count].current =
|
||||
((static_cast<uint32_t>(pdpStatus.bits.chan1_h8) << 2) |
|
||||
@@ -650,8 +665,9 @@ HAL_PowerDistributionChannelData* HAL_GetPDPStreamData(HAL_PDPHandle handle,
|
||||
|
||||
for (uint32_t i = 0; i < messagesRead; i++) {
|
||||
PdpStatus2 pdpStatus;
|
||||
std::memcpy(pdpStatus.data, messages[i].data, sizeof(messages[i].data));
|
||||
uint32_t timestamp = messages[i].timeStamp;
|
||||
std::memcpy(pdpStatus.data, messages[i].message.message.data,
|
||||
sizeof(pdpStatus));
|
||||
uint64_t timestamp = messages[i].message.timeStamp;
|
||||
|
||||
retData[*count].current =
|
||||
((static_cast<uint32_t>(pdpStatus.bits.chan7_h8) << 2) |
|
||||
@@ -706,8 +722,9 @@ HAL_PowerDistributionChannelData* HAL_GetPDPStreamData(HAL_PDPHandle handle,
|
||||
|
||||
for (uint32_t i = 0; i < messagesRead; i++) {
|
||||
PdpStatus3 pdpStatus;
|
||||
std::memcpy(pdpStatus.data, messages[i].data, sizeof(messages[i].data));
|
||||
uint32_t timestamp = messages[i].timeStamp;
|
||||
std::memcpy(pdpStatus.data, messages[i].message.message.data,
|
||||
sizeof(pdpStatus));
|
||||
uint64_t timestamp = messages[i].message.timeStamp;
|
||||
|
||||
retData[*count].current =
|
||||
((static_cast<uint32_t>(pdpStatus.bits.chan13_h8) << 2) |
|
||||
|
||||
@@ -23,10 +23,12 @@ extern "C" {
|
||||
/**
|
||||
* Initializes a Power Distribution Panel.
|
||||
*
|
||||
* @param busID the can bus id
|
||||
* @param module the module number to initialize
|
||||
* @return the created PDP
|
||||
*/
|
||||
HAL_PDPHandle HAL_InitializePDP(int32_t module, const char* allocationLocation,
|
||||
HAL_PDPHandle HAL_InitializePDP(int32_t busId, int32_t module,
|
||||
const char* allocationLocation,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,9 @@ void InitializePorts() {}
|
||||
} // namespace hal::init
|
||||
|
||||
extern "C" {
|
||||
int32_t HAL_GetNumCanBuses(void) {
|
||||
return kNumCanBuses;
|
||||
}
|
||||
int32_t HAL_GetNumAnalogInputs(void) {
|
||||
return kNumAnalogInputs;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace hal {
|
||||
|
||||
constexpr int32_t kNumCanBuses = 2;
|
||||
constexpr int32_t kNumSmartIo = 5;
|
||||
constexpr int32_t kNumAccumulators = 0;
|
||||
constexpr int32_t kNumAnalogInputs = 8;
|
||||
|
||||
@@ -20,7 +20,7 @@ using namespace hal;
|
||||
extern "C" {
|
||||
|
||||
HAL_PowerDistributionHandle HAL_InitializePowerDistribution(
|
||||
int32_t moduleNumber, HAL_PowerDistributionType type,
|
||||
int32_t busId, int32_t moduleNumber, HAL_PowerDistributionType type,
|
||||
const char* allocationLocation, int32_t* status) {
|
||||
if (type == HAL_PowerDistributionType::HAL_PowerDistributionType_kAutomatic) {
|
||||
if (moduleNumber != HAL_DEFAULT_POWER_DISTRIBUTION_MODULE) {
|
||||
@@ -46,7 +46,7 @@ HAL_PowerDistributionHandle HAL_InitializePowerDistribution(
|
||||
} while (true);
|
||||
|
||||
// Try PDP first
|
||||
auto pdpHandle = HAL_InitializePDP(0, allocationLocation, status);
|
||||
auto pdpHandle = HAL_InitializePDP(busId, 0, allocationLocation, status);
|
||||
if (pdpHandle != HAL_kInvalidHandle) {
|
||||
*status = 0;
|
||||
HAL_GetPDPVoltage(pdpHandle, status);
|
||||
@@ -56,7 +56,7 @@ HAL_PowerDistributionHandle HAL_InitializePowerDistribution(
|
||||
HAL_CleanPDP(pdpHandle);
|
||||
}
|
||||
*status = 0;
|
||||
auto pdhHandle = HAL_InitializeREVPDH(1, allocationLocation, status);
|
||||
auto pdhHandle = HAL_InitializeREVPDH(busId, 1, allocationLocation, status);
|
||||
return static_cast<HAL_PowerDistributionHandle>(pdhHandle);
|
||||
}
|
||||
|
||||
@@ -65,13 +65,13 @@ HAL_PowerDistributionHandle HAL_InitializePowerDistribution(
|
||||
moduleNumber = 0;
|
||||
}
|
||||
return static_cast<HAL_PowerDistributionHandle>(
|
||||
HAL_InitializePDP(moduleNumber, allocationLocation, status));
|
||||
HAL_InitializePDP(busId, moduleNumber, allocationLocation, status));
|
||||
} else {
|
||||
if (moduleNumber == HAL_DEFAULT_POWER_DISTRIBUTION_MODULE) {
|
||||
moduleNumber = 1;
|
||||
}
|
||||
return static_cast<HAL_PowerDistributionHandle>(
|
||||
HAL_InitializeREVPDH(moduleNumber, allocationLocation, status));
|
||||
HAL_InitializeREVPDH(busId, moduleNumber, allocationLocation, status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,95 +91,85 @@ extern "C" {
|
||||
|
||||
static PDH_status_0_t HAL_ReadREVPDHStatus0(HAL_CANHandle hcan,
|
||||
int32_t* status) {
|
||||
uint8_t packedData[8] = {0};
|
||||
int32_t length = 0;
|
||||
uint64_t timestamp = 0;
|
||||
HAL_CANReceiveMessage message;
|
||||
PDH_status_0_t result = {};
|
||||
|
||||
HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_0_FRAME_API, packedData, &length,
|
||||
×tamp, kPDHFrameStatus0Timeout * 2, status);
|
||||
HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_0_FRAME_API, &message,
|
||||
kPDHFrameStatus0Timeout * 2, status);
|
||||
|
||||
if (*status != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
PDH_status_0_unpack(&result, packedData, PDH_STATUS_0_LENGTH);
|
||||
PDH_status_0_unpack(&result, message.message.data, PDH_STATUS_0_LENGTH);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static PDH_status_1_t HAL_ReadREVPDHStatus1(HAL_CANHandle hcan,
|
||||
int32_t* status) {
|
||||
uint8_t packedData[8] = {0};
|
||||
int32_t length = 0;
|
||||
uint64_t timestamp = 0;
|
||||
HAL_CANReceiveMessage message;
|
||||
PDH_status_1_t result = {};
|
||||
|
||||
HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_1_FRAME_API, packedData, &length,
|
||||
×tamp, kPDHFrameStatus1Timeout * 2, status);
|
||||
HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_1_FRAME_API, &message,
|
||||
kPDHFrameStatus1Timeout * 2, status);
|
||||
|
||||
if (*status != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
PDH_status_1_unpack(&result, packedData, PDH_STATUS_1_LENGTH);
|
||||
PDH_status_1_unpack(&result, message.message.data, PDH_STATUS_1_LENGTH);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static PDH_status_2_t HAL_ReadREVPDHStatus2(HAL_CANHandle hcan,
|
||||
int32_t* status) {
|
||||
uint8_t packedData[8] = {0};
|
||||
int32_t length = 0;
|
||||
uint64_t timestamp = 0;
|
||||
HAL_CANReceiveMessage message;
|
||||
PDH_status_2_t result = {};
|
||||
|
||||
HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_2_FRAME_API, packedData, &length,
|
||||
×tamp, kPDHFrameStatus2Timeout * 2, status);
|
||||
HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_2_FRAME_API, &message,
|
||||
kPDHFrameStatus2Timeout * 2, status);
|
||||
|
||||
if (*status != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
PDH_status_2_unpack(&result, packedData, PDH_STATUS_2_LENGTH);
|
||||
PDH_status_2_unpack(&result, message.message.data, PDH_STATUS_2_LENGTH);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static PDH_status_3_t HAL_ReadREVPDHStatus3(HAL_CANHandle hcan,
|
||||
int32_t* status) {
|
||||
uint8_t packedData[8] = {0};
|
||||
int32_t length = 0;
|
||||
uint64_t timestamp = 0;
|
||||
HAL_CANReceiveMessage message;
|
||||
PDH_status_3_t result = {};
|
||||
|
||||
HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_3_FRAME_API, packedData, &length,
|
||||
×tamp, kPDHFrameStatus3Timeout * 2, status);
|
||||
HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_3_FRAME_API, &message,
|
||||
kPDHFrameStatus3Timeout * 2, status);
|
||||
|
||||
if (*status != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
PDH_status_3_unpack(&result, packedData, PDH_STATUS_3_LENGTH);
|
||||
PDH_status_3_unpack(&result, message.message.data, PDH_STATUS_3_LENGTH);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static PDH_status_4_t HAL_ReadREVPDHStatus4(HAL_CANHandle hcan,
|
||||
int32_t* status) {
|
||||
uint8_t packedData[8] = {0};
|
||||
int32_t length = 0;
|
||||
uint64_t timestamp = 0;
|
||||
HAL_CANReceiveMessage message;
|
||||
PDH_status_4_t result = {};
|
||||
|
||||
HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_4_FRAME_API, packedData, &length,
|
||||
×tamp, kPDHFrameStatus4Timeout * 2, status);
|
||||
HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_4_FRAME_API, &message,
|
||||
kPDHFrameStatus4Timeout * 2, status);
|
||||
|
||||
if (*status != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
PDH_status_4_unpack(&result, packedData, PDH_STATUS_4_LENGTH);
|
||||
PDH_status_4_unpack(&result, message.message.data, PDH_STATUS_4_LENGTH);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -199,7 +189,7 @@ PDH_status_4_t HAL_GetREVPDHStatus4(HAL_REVPDHHandle handle, int32_t* status) {
|
||||
return statusFrame;
|
||||
}
|
||||
|
||||
HAL_REVPDHHandle HAL_InitializeREVPDH(int32_t module,
|
||||
HAL_REVPDHHandle HAL_InitializeREVPDH(int32_t busId, int32_t module,
|
||||
const char* allocationLocation,
|
||||
int32_t* status) {
|
||||
hal::init::CheckInit();
|
||||
@@ -225,7 +215,7 @@ HAL_REVPDHHandle HAL_InitializeREVPDH(int32_t module,
|
||||
}
|
||||
|
||||
HAL_CANHandle hcan =
|
||||
HAL_InitializeCAN(manufacturer, module, deviceType, status);
|
||||
HAL_InitializeCAN(busId, manufacturer, module, deviceType, status);
|
||||
|
||||
if (*status != 0) {
|
||||
REVPDHHandles->Free(handle);
|
||||
@@ -454,14 +444,16 @@ void HAL_SetREVPDHSwitchableChannel(HAL_REVPDHHandle handle, HAL_Bool enabled,
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t packedData[8] = {0};
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
PDH_set_switch_channel_t frame;
|
||||
frame.output_set_value = enabled;
|
||||
PDH_set_switch_channel_pack(packedData, &frame,
|
||||
PDH_set_switch_channel_pack(message.data, &frame,
|
||||
PDH_SET_SWITCH_CHANNEL_LENGTH);
|
||||
message.dataSize = PDH_SET_SWITCH_CHANNEL_LENGTH;
|
||||
|
||||
HAL_WriteCANPacket(hpdh->hcan, packedData, PDH_SET_SWITCH_CHANNEL_LENGTH,
|
||||
PDH_SET_SWITCH_CHANNEL_FRAME_API, status);
|
||||
HAL_WriteCANPacket(hpdh->hcan, PDH_SET_SWITCH_CHANNEL_FRAME_API, &message,
|
||||
status);
|
||||
}
|
||||
|
||||
HAL_Bool HAL_GetREVPDHSwitchableChannelState(HAL_REVPDHHandle handle,
|
||||
@@ -490,9 +482,6 @@ void HAL_GetREVPDHVersion(HAL_REVPDHHandle handle,
|
||||
HAL_PowerDistributionVersion* version,
|
||||
int32_t* status) {
|
||||
std::memset(version, 0, sizeof(*version));
|
||||
uint8_t packedData[8] = {0};
|
||||
int32_t length = 0;
|
||||
uint64_t timestamp = 0;
|
||||
PDH_version_t result = {};
|
||||
auto hpdh = REVPDHHandles->Get(handle);
|
||||
if (hpdh == nullptr) {
|
||||
@@ -512,17 +501,20 @@ void HAL_GetREVPDHVersion(HAL_REVPDHHandle handle,
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_WriteCANRTRFrame(hpdh->hcan, PDH_VERSION_LENGTH, PDH_VERSION_FRAME_API,
|
||||
status);
|
||||
HAL_CANMessage rtrmessage;
|
||||
std::memset(&rtrmessage, 0, sizeof(rtrmessage));
|
||||
rtrmessage.dataSize = PDH_VERSION_LENGTH;
|
||||
|
||||
HAL_WriteCANRTRFrame(hpdh->hcan, PDH_VERSION_FRAME_API, &rtrmessage, status);
|
||||
|
||||
if (*status != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t timeoutMs = 100;
|
||||
HAL_CANReceiveMessage message;
|
||||
for (uint32_t i = 0; i <= timeoutMs; i++) {
|
||||
HAL_ReadCANPacketNew(hpdh->hcan, PDH_VERSION_FRAME_API, packedData, &length,
|
||||
×tamp, status);
|
||||
HAL_ReadCANPacketNew(hpdh->hcan, PDH_VERSION_FRAME_API, &message, status);
|
||||
if (*status == 0) {
|
||||
break;
|
||||
}
|
||||
@@ -533,7 +525,7 @@ void HAL_GetREVPDHVersion(HAL_REVPDHHandle handle,
|
||||
return;
|
||||
}
|
||||
|
||||
PDH_version_unpack(&result, packedData, PDH_VERSION_LENGTH);
|
||||
PDH_version_unpack(&result, message.message.data, PDH_VERSION_LENGTH);
|
||||
|
||||
version->firmwareMajor = result.firmware_year;
|
||||
version->firmwareMinor = result.firmware_minor;
|
||||
@@ -640,9 +632,11 @@ void HAL_ClearREVPDHStickyFaults(HAL_REVPDHHandle handle, int32_t* status) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t packedData[8] = {0};
|
||||
HAL_WriteCANPacket(hpdh->hcan, packedData, PDH_CLEAR_FAULTS_LENGTH,
|
||||
PDH_CLEAR_FAULTS_FRAME_API, status);
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.dataSize = PDH_CLEAR_FAULTS_LENGTH;
|
||||
|
||||
HAL_WriteCANPacket(hpdh->hcan, PDH_CLEAR_FAULTS_FRAME_API, &message, status);
|
||||
}
|
||||
|
||||
uint32_t HAL_StartCANStream(HAL_CANHandle handle, int32_t apiId, int32_t depth,
|
||||
@@ -717,8 +711,9 @@ HAL_PowerDistributionChannelData* HAL_GetREVPDHStreamData(
|
||||
|
||||
for (uint32_t i = 0; i < messagesRead; i++) {
|
||||
PDH_status_0_t statusFrame0;
|
||||
PDH_status_0_unpack(&statusFrame0, messages[i].data, PDH_STATUS_0_LENGTH);
|
||||
uint32_t timestamp = messages[i].timeStamp;
|
||||
PDH_status_0_unpack(&statusFrame0, messages[i].message.message.data,
|
||||
PDH_STATUS_0_LENGTH);
|
||||
uint32_t timestamp = messages[i].message.timeStamp;
|
||||
|
||||
retData[*count].current =
|
||||
PDH_status_0_channel_0_current_decode(statusFrame0.channel_0_current);
|
||||
@@ -761,8 +756,9 @@ HAL_PowerDistributionChannelData* HAL_GetREVPDHStreamData(
|
||||
|
||||
for (uint32_t i = 0; i < messagesRead; i++) {
|
||||
PDH_status_1_t statusFrame1;
|
||||
PDH_status_1_unpack(&statusFrame1, messages[i].data, PDH_STATUS_1_LENGTH);
|
||||
uint32_t timestamp = messages[i].timeStamp;
|
||||
PDH_status_1_unpack(&statusFrame1, messages[i].message.message.data,
|
||||
PDH_STATUS_1_LENGTH);
|
||||
uint32_t timestamp = messages[i].message.timeStamp;
|
||||
|
||||
retData[*count].current =
|
||||
PDH_status_1_channel_6_current_decode(statusFrame1.channel_6_current);
|
||||
@@ -805,8 +801,9 @@ HAL_PowerDistributionChannelData* HAL_GetREVPDHStreamData(
|
||||
|
||||
for (uint32_t i = 0; i < messagesRead; i++) {
|
||||
PDH_status_2_t statusFrame2;
|
||||
PDH_status_2_unpack(&statusFrame2, messages[i].data, PDH_STATUS_2_LENGTH);
|
||||
uint32_t timestamp = messages[i].timeStamp;
|
||||
PDH_status_2_unpack(&statusFrame2, messages[i].message.message.data,
|
||||
PDH_STATUS_2_LENGTH);
|
||||
uint32_t timestamp = messages[i].message.timeStamp;
|
||||
|
||||
retData[*count].current =
|
||||
PDH_status_2_channel_12_current_decode(statusFrame2.channel_12_current);
|
||||
@@ -849,8 +846,9 @@ HAL_PowerDistributionChannelData* HAL_GetREVPDHStreamData(
|
||||
|
||||
for (uint32_t i = 0; i < messagesRead; i++) {
|
||||
PDH_status_3_t statusFrame3;
|
||||
PDH_status_3_unpack(&statusFrame3, messages[i].data, PDH_STATUS_3_LENGTH);
|
||||
uint32_t timestamp = messages[i].timeStamp;
|
||||
PDH_status_3_unpack(&statusFrame3, messages[i].message.message.data,
|
||||
PDH_STATUS_3_LENGTH);
|
||||
uint32_t timestamp = messages[i].message.timeStamp;
|
||||
|
||||
retData[*count].current =
|
||||
PDH_status_3_channel_18_current_decode(statusFrame3.channel_18_current);
|
||||
|
||||
@@ -25,7 +25,7 @@ extern "C" {
|
||||
* @param module the device CAN ID (1 .. 63)
|
||||
* @return the created PDH handle
|
||||
*/
|
||||
HAL_REVPDHHandle HAL_InitializeREVPDH(int32_t module,
|
||||
HAL_REVPDHHandle HAL_InitializeREVPDH(int32_t busId, int32_t module,
|
||||
const char* allocationLocation,
|
||||
int32_t* status);
|
||||
|
||||
|
||||
@@ -84,37 +84,33 @@ void InitializeREVPH() {
|
||||
} // namespace hal::init
|
||||
|
||||
static PH_status_0_t HAL_ReadREVPHStatus0(HAL_CANHandle hcan, int32_t* status) {
|
||||
uint8_t packedData[8] = {0};
|
||||
int32_t length = 0;
|
||||
uint64_t timestamp = 0;
|
||||
HAL_CANReceiveMessage message;
|
||||
PH_status_0_t result = {};
|
||||
|
||||
HAL_ReadCANPacketTimeout(hcan, PH_STATUS_0_FRAME_API, packedData, &length,
|
||||
×tamp, kPHFrameStatus0Timeout * 2, status);
|
||||
HAL_ReadCANPacketTimeout(hcan, PH_STATUS_0_FRAME_API, &message,
|
||||
kPHFrameStatus0Timeout * 2, status);
|
||||
|
||||
if (*status != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
PH_status_0_unpack(&result, packedData, PH_STATUS_0_LENGTH);
|
||||
PH_status_0_unpack(&result, message.message.data, PH_STATUS_0_LENGTH);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static PH_status_1_t HAL_ReadREVPHStatus1(HAL_CANHandle hcan, int32_t* status) {
|
||||
uint8_t packedData[8] = {0};
|
||||
int32_t length = 0;
|
||||
uint64_t timestamp = 0;
|
||||
HAL_CANReceiveMessage message;
|
||||
PH_status_1_t result = {};
|
||||
|
||||
HAL_ReadCANPacketTimeout(hcan, PH_STATUS_1_FRAME_API, packedData, &length,
|
||||
×tamp, kPHFrameStatus1Timeout * 2, status);
|
||||
HAL_ReadCANPacketTimeout(hcan, PH_STATUS_1_FRAME_API, &message,
|
||||
kPHFrameStatus1Timeout * 2, status);
|
||||
|
||||
if (*status != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
PH_status_1_unpack(&result, packedData, PH_STATUS_1_LENGTH);
|
||||
PH_status_1_unpack(&result, message.message.data, PH_STATUS_1_LENGTH);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -181,17 +177,21 @@ static void HAL_UpdateDesiredREVPHSolenoidState(REV_PHObj* hph,
|
||||
}
|
||||
|
||||
static void HAL_SendREVPHSolenoidsState(REV_PHObj* hph, int32_t* status) {
|
||||
uint8_t packedData[PH_SET_ALL_LENGTH] = {0};
|
||||
PH_set_all_pack(packedData, &(hph->desiredSolenoidsState), PH_SET_ALL_LENGTH);
|
||||
HAL_WriteCANPacketRepeating(hph->hcan, packedData, PH_SET_ALL_LENGTH,
|
||||
PH_SET_ALL_FRAME_API, hph->controlPeriod, status);
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.dataSize = PH_SET_ALL_LENGTH;
|
||||
PH_set_all_pack(message.data, &(hph->desiredSolenoidsState),
|
||||
PH_SET_ALL_LENGTH);
|
||||
|
||||
HAL_WriteCANPacketRepeating(hph->hcan, PH_SET_ALL_FRAME_API, &message,
|
||||
hph->controlPeriod, status);
|
||||
}
|
||||
|
||||
static HAL_Bool HAL_CheckREVPHPulseTime(int32_t time) {
|
||||
return ((time > 0) && (time <= HAL_REVPH_MAX_PULSE_TIME)) ? 1 : 0;
|
||||
}
|
||||
|
||||
HAL_REVPHHandle HAL_InitializeREVPH(int32_t module,
|
||||
HAL_REVPHHandle HAL_InitializeREVPH(int32_t busId, int32_t module,
|
||||
const char* allocationLocation,
|
||||
int32_t* status) {
|
||||
hal::init::CheckInit();
|
||||
@@ -217,7 +217,7 @@ HAL_REVPHHandle HAL_InitializeREVPH(int32_t module,
|
||||
}
|
||||
|
||||
HAL_CANHandle hcan =
|
||||
HAL_InitializeCAN(manufacturer, module, deviceType, status);
|
||||
HAL_InitializeCAN(busId, manufacturer, module, deviceType, status);
|
||||
|
||||
if (*status != 0) {
|
||||
REVPHHandles->Free(handle);
|
||||
@@ -291,11 +291,13 @@ void HAL_SetREVPHCompressorConfig(HAL_REVPHHandle handle,
|
||||
frameData.force_disable = config->forceDisable;
|
||||
frameData.use_digital = config->useDigital;
|
||||
|
||||
uint8_t packedData[PH_COMPRESSOR_CONFIG_LENGTH] = {0};
|
||||
PH_compressor_config_pack(packedData, &frameData,
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.dataSize = PH_COMPRESSOR_CONFIG_LENGTH;
|
||||
PH_compressor_config_pack(message.data, &frameData,
|
||||
PH_COMPRESSOR_CONFIG_LENGTH);
|
||||
HAL_WriteCANPacket(ph->hcan, packedData, PH_COMPRESSOR_CONFIG_LENGTH,
|
||||
PH_COMPRESSOR_CONFIG_API, status);
|
||||
|
||||
HAL_WriteCANPacket(ph->hcan, PH_COMPRESSOR_CONFIG_API, &message, status);
|
||||
}
|
||||
|
||||
void HAL_SetREVPHClosedLoopControlDisabled(HAL_REVPHHandle handle,
|
||||
@@ -480,9 +482,6 @@ double HAL_GetREVPHSolenoidVoltage(HAL_REVPHHandle handle, int32_t* status) {
|
||||
void HAL_GetREVPHVersion(HAL_REVPHHandle handle, HAL_REVPHVersion* version,
|
||||
int32_t* status) {
|
||||
std::memset(version, 0, sizeof(*version));
|
||||
uint8_t packedData[8] = {0};
|
||||
int32_t length = 0;
|
||||
uint64_t timestamp = 0;
|
||||
PH_version_t result = {};
|
||||
auto ph = REVPHHandles->Get(handle);
|
||||
if (ph == nullptr) {
|
||||
@@ -502,17 +501,20 @@ void HAL_GetREVPHVersion(HAL_REVPHHandle handle, HAL_REVPHVersion* version,
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_WriteCANRTRFrame(ph->hcan, PH_VERSION_LENGTH, PH_VERSION_FRAME_API,
|
||||
status);
|
||||
HAL_CANMessage rtrmessage;
|
||||
std::memset(&rtrmessage, 0, sizeof(rtrmessage));
|
||||
rtrmessage.dataSize = PH_VERSION_LENGTH;
|
||||
|
||||
HAL_WriteCANRTRFrame(ph->hcan, PH_VERSION_FRAME_API, &rtrmessage, status);
|
||||
|
||||
if (*status != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t timeoutMs = 100;
|
||||
HAL_CANReceiveMessage message;
|
||||
for (uint32_t i = 0; i <= timeoutMs; i++) {
|
||||
HAL_ReadCANPacketNew(ph->hcan, PH_VERSION_FRAME_API, packedData, &length,
|
||||
×tamp, status);
|
||||
HAL_ReadCANPacketNew(ph->hcan, PH_VERSION_FRAME_API, &message, status);
|
||||
if (*status == 0) {
|
||||
break;
|
||||
}
|
||||
@@ -523,7 +525,7 @@ void HAL_GetREVPHVersion(HAL_REVPHHandle handle, HAL_REVPHVersion* version,
|
||||
return;
|
||||
}
|
||||
|
||||
PH_version_unpack(&result, packedData, PH_VERSION_LENGTH);
|
||||
PH_version_unpack(&result, message.message.data, PH_VERSION_LENGTH);
|
||||
|
||||
version->firmwareMajor = result.firmware_year;
|
||||
version->firmwareMinor = result.firmware_minor;
|
||||
@@ -683,10 +685,11 @@ void HAL_FireREVPHOneShot(HAL_REVPHHandle handle, int32_t index, int32_t durMs,
|
||||
}
|
||||
|
||||
// Send pulse command
|
||||
uint8_t packedData[PH_PULSE_ONCE_LENGTH] = {0};
|
||||
PH_pulse_once_pack(packedData, &pulse, PH_PULSE_ONCE_LENGTH);
|
||||
HAL_WriteCANPacket(ph->hcan, packedData, PH_PULSE_ONCE_LENGTH,
|
||||
PH_PULSE_ONCE_FRAME_API, status);
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.dataSize = PH_PULSE_ONCE_LENGTH;
|
||||
PH_pulse_once_pack(message.data, &pulse, PH_PULSE_ONCE_LENGTH);
|
||||
HAL_WriteCANPacket(ph->hcan, PH_PULSE_ONCE_FRAME_API, &message, status);
|
||||
}
|
||||
|
||||
void HAL_GetREVPHFaults(HAL_REVPHHandle handle, HAL_REVPHFaults* faults,
|
||||
@@ -752,9 +755,11 @@ void HAL_ClearREVPHStickyFaults(HAL_REVPHHandle handle, int32_t* status) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t packedData[8] = {0};
|
||||
HAL_WriteCANPacket(ph->hcan, packedData, PH_CLEAR_FAULTS_LENGTH,
|
||||
PH_CLEAR_FAULTS_FRAME_API, status);
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.dataSize = PH_CLEAR_FAULTS_LENGTH;
|
||||
|
||||
HAL_WriteCANPacket(ph->hcan, PH_CLEAR_FAULTS_FRAME_API, &message, status);
|
||||
}
|
||||
|
||||
int32_t HAL_GetREVPHSolenoidDisabledList(HAL_REVPHHandle handle,
|
||||
|
||||
Reference in New Issue
Block a user