mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[hal, wpilib] Rewrite CAN APIs (#7798)
This commit is contained in:
@@ -4,34 +4,28 @@
|
||||
|
||||
package edu.wpi.first.hal;
|
||||
|
||||
import edu.wpi.first.hal.can.CANReceiveMessage;
|
||||
|
||||
/**
|
||||
* CAN API HAL JNI Functions.
|
||||
*
|
||||
* @see "hal/CANAPI.h"
|
||||
*/
|
||||
public class CANAPIJNI extends JNIWrapper {
|
||||
/**
|
||||
* 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.
|
||||
* @see "HAL_GetCANPacketBaseTime"
|
||||
*/
|
||||
public static native long getCANPacketBaseTime();
|
||||
|
||||
/**
|
||||
* Initializes a CAN device.
|
||||
*
|
||||
* <p>These follow the FIRST standard CAN layout.
|
||||
* https://docs.wpilib.org/en/stable/docs/software/can-devices/can-addressing.html
|
||||
*
|
||||
* @param busId the bus ID
|
||||
* @param manufacturer the can manufacturer
|
||||
* @param deviceId the device ID (0-63)
|
||||
* @param deviceType the device type
|
||||
* @return the created CAN handle
|
||||
* @see "HAL_InitializeCAN"
|
||||
*/
|
||||
public static native int initializeCAN(int manufacturer, int deviceId, int deviceType);
|
||||
public static native int initializeCAN(int busId, int manufacturer, int deviceId, int deviceType);
|
||||
|
||||
/**
|
||||
* Frees a CAN device.
|
||||
@@ -47,11 +41,14 @@ public class CANAPIJNI extends JNIWrapper {
|
||||
* <p>This ID is 10 bits.
|
||||
*
|
||||
* @param handle the CAN handle
|
||||
* @param data the data to write (0-8 bytes)
|
||||
* @param apiId the ID to write (0-1023 bits)
|
||||
* @param data the data to send.
|
||||
* @param dataLength the length of data to send
|
||||
* @param flags the message flags
|
||||
* @see "HAL_WriteCANPacket"
|
||||
*/
|
||||
public static native void writeCANPacket(int handle, byte[] data, int apiId);
|
||||
public static native void writeCANPacket(
|
||||
int handle, int apiId, byte[] data, int dataLength, int flags);
|
||||
|
||||
/**
|
||||
* Writes a repeating packet to the CAN device with a specific ID.
|
||||
@@ -61,13 +58,15 @@ public class CANAPIJNI extends JNIWrapper {
|
||||
* <p>The RoboRIO will automatically repeat the packet at the specified interval
|
||||
*
|
||||
* @param handle the CAN handle
|
||||
* @param data the data to write (0-8 bytes)
|
||||
* @param apiId the ID to write (0-1023)
|
||||
* @param data the data to send.
|
||||
* @param dataLength the length of data to send
|
||||
* @param flags the message flags
|
||||
* @param repeatMs the period to repeat in ms
|
||||
* @see "HAL_WriteCANPacketRepeating"
|
||||
*/
|
||||
public static native void writeCANPacketRepeating(
|
||||
int handle, byte[] data, int apiId, int repeatMs);
|
||||
int handle, int apiId, byte[] data, int dataLength, int flags, int repeatMs);
|
||||
|
||||
/**
|
||||
* Writes an RTR frame of the specified length to the CAN device with the specific ID.
|
||||
@@ -76,11 +75,14 @@ public class CANAPIJNI extends JNIWrapper {
|
||||
* is unspecified.
|
||||
*
|
||||
* @param handle the CAN handle
|
||||
* @param length the length of data to request (0-8)
|
||||
* @param apiId the ID to write (0-1023)
|
||||
* @param data the data to send.
|
||||
* @param dataLength the length of data to send
|
||||
* @param flags the message flags
|
||||
* @see "HAL_WriteCANRTRFrame"
|
||||
*/
|
||||
public static native void writeCANRTRFrame(int handle, int length, int apiId);
|
||||
public static native void writeCANRTRFrame(
|
||||
int handle, int apiId, byte[] data, int dataLength, int flags);
|
||||
|
||||
/**
|
||||
* Writes a packet to the CAN device with a specific ID without throwing on error.
|
||||
@@ -88,12 +90,15 @@ public class CANAPIJNI extends JNIWrapper {
|
||||
* <p>This ID is 10 bits.
|
||||
*
|
||||
* @param handle the CAN handle
|
||||
* @param data the data to write (0-8 bytes)
|
||||
* @param apiId the ID to write (0-1023 bits)
|
||||
* @param data the data to send.
|
||||
* @param dataLength the length of data to send
|
||||
* @param flags the message flags
|
||||
* @return Error status variable. 0 on success.
|
||||
* @see "HAL_WriteCANPacket"
|
||||
*/
|
||||
public static native int writeCANPacketNoThrow(int handle, byte[] data, int apiId);
|
||||
public static native int writeCANPacketNoThrow(
|
||||
int handle, int apiId, byte[] data, int dataLength, int flags);
|
||||
|
||||
/**
|
||||
* Writes a repeating packet to the CAN device with a specific ID without throwing on error.
|
||||
@@ -103,14 +108,16 @@ public class CANAPIJNI extends JNIWrapper {
|
||||
* <p>The RoboRIO will automatically repeat the packet at the specified interval
|
||||
*
|
||||
* @param handle the CAN handle
|
||||
* @param data the data to write (0-8 bytes)
|
||||
* @param apiId the ID to write (0-1023)
|
||||
* @param data the data to send.
|
||||
* @param dataLength the length of data to send
|
||||
* @param flags the message flags
|
||||
* @param repeatMs the period to repeat in ms
|
||||
* @return Error status variable. 0 on success.
|
||||
* @see "HAL_WriteCANPacketRepeating"
|
||||
*/
|
||||
public static native int writeCANPacketRepeatingNoThrow(
|
||||
int handle, byte[] data, int apiId, int repeatMs);
|
||||
int handle, int apiId, byte[] data, int dataLength, int flags, int repeatMs);
|
||||
|
||||
/**
|
||||
* Writes an RTR frame of the specified length to the CAN device with the specific ID without
|
||||
@@ -119,13 +126,16 @@ public class CANAPIJNI extends JNIWrapper {
|
||||
* <p>By spec, the length must be equal to the length sent by the other device, otherwise behavior
|
||||
* is unspecified.
|
||||
*
|
||||
* @param handle the CAN handle
|
||||
* @param length the length of data to request (0-8)
|
||||
* @param handle the CAN handlee
|
||||
* @param apiId the ID to write (0-1023)
|
||||
* @param data the data to send.
|
||||
* @param dataLength the length of data to send
|
||||
* @param flags the message flags
|
||||
* @return Error status variable. 0 on success.
|
||||
* @see "HAL_WriteCANRTRFrame"
|
||||
*/
|
||||
public static native int writeCANRTRFrameNoThrow(int handle, int length, int apiId);
|
||||
public static native int writeCANRTRFrameNoThrow(
|
||||
int handle, int apiId, byte[] data, int dataLength, int flags);
|
||||
|
||||
/**
|
||||
* Stops a repeating packet with a specific ID.
|
||||
@@ -146,11 +156,11 @@ public class CANAPIJNI extends JNIWrapper {
|
||||
*
|
||||
* @param handle the CAN handle
|
||||
* @param apiId the ID to read (0-1023)
|
||||
* @param data the packet data (8 bytes)
|
||||
* @param data the received message
|
||||
* @return true on success, false on error
|
||||
* @see "HAL_ReadCANPacketNew"
|
||||
*/
|
||||
public static native boolean readCANPacketNew(int handle, int apiId, CANData data);
|
||||
public static native boolean readCANPacketNew(int handle, int apiId, CANReceiveMessage data);
|
||||
|
||||
/**
|
||||
* Reads a CAN packet. The will continuously return the last packet received, without accounting
|
||||
@@ -158,11 +168,11 @@ public class CANAPIJNI extends JNIWrapper {
|
||||
*
|
||||
* @param handle the CAN handle
|
||||
* @param apiId the ID to read (0-1023)
|
||||
* @param data the packet data (8 bytes)
|
||||
* @param data the received message
|
||||
* @return true on success, false on error
|
||||
* @see "HAL_ReadCANPacketLatest"
|
||||
*/
|
||||
public static native boolean readCANPacketLatest(int handle, int apiId, CANData data);
|
||||
public static native boolean readCANPacketLatest(int handle, int apiId, CANReceiveMessage data);
|
||||
|
||||
/**
|
||||
* Reads a CAN packet. The will return the last packet received until the packet is older then the
|
||||
@@ -170,13 +180,13 @@ public class CANAPIJNI extends JNIWrapper {
|
||||
*
|
||||
* @param handle the CAN handle
|
||||
* @param apiId the ID to read (0-1023)
|
||||
* @param data the received message
|
||||
* @param timeoutMs the timeout time for the packet
|
||||
* @param data the packet data (8 bytes)
|
||||
* @return true on success, false on error
|
||||
* @see "HAL_ReadCANPacketTimeout"
|
||||
*/
|
||||
public static native boolean readCANPacketTimeout(
|
||||
int handle, int apiId, int timeoutMs, CANData data);
|
||||
int handle, int apiId, CANReceiveMessage data, int timeoutMs);
|
||||
|
||||
/** Utility class. */
|
||||
private CANAPIJNI() {}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.hal;
|
||||
|
||||
/** Represents a received CAN message. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public class CANData {
|
||||
/** Contents of the CAN frame. */
|
||||
public final byte[] data = new byte[8];
|
||||
|
||||
/** Length of the frame in bytes. */
|
||||
public int length;
|
||||
|
||||
/** CAN frame timestamp in milliseconds. */
|
||||
public long timestamp;
|
||||
|
||||
/** Default constructor. */
|
||||
public CANData() {}
|
||||
|
||||
/**
|
||||
* API used from JNI to set the data.
|
||||
*
|
||||
* @param length Length of packet in bytes.
|
||||
* @param timestamp CAN frame timestamp in milliseconds.
|
||||
* @return Buffer to place CAN frame data in.
|
||||
*/
|
||||
@SuppressWarnings("PMD.MethodReturnsInternalArray")
|
||||
public byte[] setData(int length, long timestamp) {
|
||||
this.length = length;
|
||||
this.timestamp = timestamp;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -13,11 +13,12 @@ public class CTREPCMJNI extends JNIWrapper {
|
||||
/**
|
||||
* Initializes a PCM.
|
||||
*
|
||||
* @param busId the bus id
|
||||
* @param module the CAN ID to initialize
|
||||
* @return the created PH handle
|
||||
* @see "HAL_InitializeCTREPCM"
|
||||
*/
|
||||
public static native int initialize(int module);
|
||||
public static native int initialize(int busId, int module);
|
||||
|
||||
/**
|
||||
* Frees a PCM handle.
|
||||
|
||||
@@ -10,6 +10,14 @@ package edu.wpi.first.hal;
|
||||
* @see "hal/Ports.h"
|
||||
*/
|
||||
public class PortsJNI extends JNIWrapper {
|
||||
/**
|
||||
* Gets the number of can buses in the current system.
|
||||
*
|
||||
* @return the number of can buses
|
||||
* @see "HAL_GetNumCanBuses"
|
||||
*/
|
||||
public static native int getNumCanBuses();
|
||||
|
||||
/**
|
||||
* Gets the number of analog inputs in the current system.
|
||||
*
|
||||
|
||||
@@ -25,12 +25,13 @@ public class PowerDistributionJNI extends JNIWrapper {
|
||||
/**
|
||||
* Initializes a Power Distribution Panel.
|
||||
*
|
||||
* @param busId the bus id
|
||||
* @param module the module number to initialize
|
||||
* @param type the type of module to initialize
|
||||
* @return the created PowerDistribution handle
|
||||
* @see "HAL_InitializePowerDistribution"
|
||||
*/
|
||||
public static native int initialize(int module, int type);
|
||||
public static native int initialize(int busId, int module, int type);
|
||||
|
||||
/**
|
||||
* Cleans a PowerDistribution module.
|
||||
|
||||
@@ -25,11 +25,12 @@ public class REVPHJNI extends JNIWrapper {
|
||||
/**
|
||||
* Initializes a PH.
|
||||
*
|
||||
* @param busId the bus id
|
||||
* @param module the CAN ID to initialize
|
||||
* @return the created PH handle
|
||||
* @see "HAL_InitializeREVPH"
|
||||
*/
|
||||
public static native int initialize(int module);
|
||||
public static native int initialize(int busId, int module);
|
||||
|
||||
/**
|
||||
* Frees a PH handle.
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.hal.can;
|
||||
|
||||
import edu.wpi.first.hal.communication.NIRioStatus;
|
||||
import edu.wpi.first.hal.util.UncleanStatusException;
|
||||
|
||||
/**
|
||||
* Checks the status of a CAN message and throws an exception of the appropriate type if necessary.
|
||||
*/
|
||||
public final class CANExceptionFactory {
|
||||
// FRC Error codes
|
||||
static final int ERR_CANSessionMux_InvalidBuffer = -44086;
|
||||
static final int ERR_CANSessionMux_MessageNotFound = -44087;
|
||||
static final int ERR_CANSessionMux_NotAllowed = -44088;
|
||||
static final int ERR_CANSessionMux_NotInitialized = -44089;
|
||||
|
||||
/**
|
||||
* Checks the status of a CAN message with the given message ID.
|
||||
*
|
||||
* @param status The CAN status.
|
||||
* @param messageID The CAN message ID.
|
||||
* @throws CANInvalidBufferException if the buffer is invalid.
|
||||
* @throws CANMessageNotAllowedException if the message isn't allowed.
|
||||
* @throws CANNotInitializedException if the CAN bus isn't initialized.
|
||||
* @throws UncleanStatusException if the status code passed in reports an error.
|
||||
*/
|
||||
public static void checkStatus(int status, int messageID) {
|
||||
switch (status) {
|
||||
case NIRioStatus.kRioStatusSuccess -> {
|
||||
// Everything is ok... don't throw.
|
||||
}
|
||||
case ERR_CANSessionMux_InvalidBuffer,
|
||||
NIRioStatus.kRIOStatusBufferInvalidSize -> throw new CANInvalidBufferException();
|
||||
case ERR_CANSessionMux_MessageNotFound,
|
||||
NIRioStatus.kRIOStatusOperationTimedOut -> throw new CANMessageNotFoundException();
|
||||
case ERR_CANSessionMux_NotAllowed,
|
||||
NIRioStatus.kRIOStatusFeatureNotSupported -> throw new CANMessageNotAllowedException(
|
||||
"MessageID = " + messageID);
|
||||
case ERR_CANSessionMux_NotInitialized,
|
||||
NIRioStatus.kRIOStatusResourceNotInitialized -> throw new CANNotInitializedException();
|
||||
default -> throw new UncleanStatusException("Fatal status code detected: " + status);
|
||||
}
|
||||
}
|
||||
|
||||
private CANExceptionFactory() {}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.hal.can;
|
||||
|
||||
/**
|
||||
* Exception indicating that a CAN driver library entry-point was passed an invalid buffer.
|
||||
* Typically, this is due to a buffer being too small to include the needed safety token.
|
||||
*/
|
||||
public class CANInvalidBufferException extends RuntimeException {
|
||||
private static final long serialVersionUID = -7993785672956997939L;
|
||||
|
||||
/** Constructs a new CANInvalidBufferException with no message. */
|
||||
public CANInvalidBufferException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new CANInvalidBufferException with {@code msg} as its detail message.
|
||||
*
|
||||
* @param msg the message
|
||||
*/
|
||||
public CANInvalidBufferException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,7 @@
|
||||
|
||||
package edu.wpi.first.hal.can;
|
||||
|
||||
import edu.wpi.first.hal.CANStreamMessage;
|
||||
import edu.wpi.first.hal.JNIWrapper;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
/**
|
||||
* CAN API HAL JNI Functions.
|
||||
@@ -34,47 +31,52 @@ public class CANJNI extends JNIWrapper {
|
||||
/**
|
||||
* Sends a CAN message.
|
||||
*
|
||||
* @param messageID The ID of the CAN message.
|
||||
* @param data The data bytes to be sent.
|
||||
* @param busId The bus ID.
|
||||
* @param messageId The ID of the CAN message.
|
||||
* @param data the data to send.
|
||||
* @param dataLength the length of data to send
|
||||
* @param flags the message flags
|
||||
* @param periodMs The period in milliseconds at which to send the message, use {@link
|
||||
* #CAN_SEND_PERIOD_NO_REPEAT} for a single send.
|
||||
* @return send status, 0 on success.
|
||||
*/
|
||||
public static native void FRCNetCommCANSessionMuxSendMessage(
|
||||
int messageID, byte[] data, int periodMs);
|
||||
public static native int sendMessage(
|
||||
int busId, int messageId, byte[] data, int dataLength, int flags, int periodMs);
|
||||
|
||||
/**
|
||||
* Receives a CAN message.
|
||||
*
|
||||
* @param messageID store for the received message ID (output parameter).
|
||||
* @param messageIDMask the message ID mask to look for
|
||||
* @param timeStamp the packet received timestamp (based off of CLOCK_MONOTONIC) (output
|
||||
* parameter).
|
||||
* @return The data bytes of the received message.
|
||||
* @param busId The bus ID.
|
||||
* @param messageId message id to look for.
|
||||
* @param message The message.
|
||||
* @return receive status, 0 on success.
|
||||
*/
|
||||
public static native byte[] FRCNetCommCANSessionMuxReceiveMessage(
|
||||
IntBuffer messageID, int messageIDMask, ByteBuffer timeStamp);
|
||||
public static native int receiveMessage(int busId, int messageId, CANReceiveMessage message);
|
||||
|
||||
/**
|
||||
* Retrieves the current status of the CAN bus.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param status The CANStatus object to hold the retrieved status.
|
||||
*/
|
||||
public static native void getCANStatus(CANStatus status);
|
||||
public static native void getCANStatus(int busId, CANStatus status);
|
||||
|
||||
/**
|
||||
* Opens a new CAN stream session for receiving CAN messages with specified filters.
|
||||
*
|
||||
* @param messageID The CAN messageID to match against. The bits of the messageID are bitwise
|
||||
* @param busId The bus ID.
|
||||
* @param messageId The CAN messageId to match against. The bits of the messageId are bitwise
|
||||
* ANDed with the messageIDMask.
|
||||
* @param messageIDMask The CAN messageIDMask is a bit-wise mask of bits in the messageID to match
|
||||
* against. This allows matching against multiple frames. For example, providing an messageID
|
||||
* @param messageIDMask The CAN messageIDMask is a bit-wise mask of bits in the messageId to match
|
||||
* against. This allows matching against multiple frames. For example, providing an messageId
|
||||
* of 0x2050001 and a mask of 0x1FFF003F would match all REV motor controller frames for a
|
||||
* device with CAN ID 1. Providing a mask of 0x1FFFFFFF means that only the exact messageID
|
||||
* device with CAN ID 1. Providing a mask of 0x1FFFFFFF means that only the exact messageId
|
||||
* will be matched. Providing a mask of 0 would match any frame of any type.
|
||||
* @param maxMessages The maximum number of messages that can be buffered in the session.
|
||||
* @return The handle to the opened CAN stream session.
|
||||
*/
|
||||
public static native int openCANStreamSession(int messageID, int messageIDMask, int maxMessages);
|
||||
public static native int openCANStreamSession(
|
||||
int busId, int messageId, int messageIDMask, int maxMessages);
|
||||
|
||||
/**
|
||||
* Closes a CAN stream session.
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.hal.can;
|
||||
|
||||
/**
|
||||
* Exception indicating that the Jaguar CAN Driver layer refused to send a restricted message ID to
|
||||
* the CAN bus.
|
||||
*/
|
||||
public class CANMessageNotAllowedException extends RuntimeException {
|
||||
private static final long serialVersionUID = -638450112427013494L;
|
||||
|
||||
/**
|
||||
* Constructs a new CANMessageNotAllowedException with {@code msg} as its detail message.
|
||||
*
|
||||
* @param msg the message
|
||||
*/
|
||||
public CANMessageNotAllowedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.hal.can;
|
||||
|
||||
/**
|
||||
* Exception indicating that a can message is not available from Network Communications. This
|
||||
* usually just means we already have the most recent value cached locally.
|
||||
*/
|
||||
public class CANMessageNotFoundException extends RuntimeException {
|
||||
private static final long serialVersionUID = 8249780881928189975L;
|
||||
|
||||
/** Constructs a new CANMessageNotFoundException with no message. */
|
||||
public CANMessageNotFoundException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new CANMessageNotFoundException with {@code msg} as its detail message.
|
||||
*
|
||||
* @param msg the message
|
||||
*/
|
||||
public CANMessageNotFoundException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.hal.can;
|
||||
|
||||
/**
|
||||
* Exception indicating that the CAN driver layer has not been initialized. This happens when an
|
||||
* entry-point is called before a CAN driver plugin has been installed.
|
||||
*/
|
||||
public class CANNotInitializedException extends RuntimeException {
|
||||
private static final long serialVersionUID = -5982895147092686594L;
|
||||
|
||||
/** Constructs a new CANNotInitializedException with no message. */
|
||||
public CANNotInitializedException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new CANNotInitializedException with {@code msg} as its detail message.
|
||||
*
|
||||
* @param msg the message
|
||||
*/
|
||||
public CANNotInitializedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.hal.can;
|
||||
|
||||
/** Represents a CAN message read from a stream. */
|
||||
public class CANReceiveMessage {
|
||||
/** The message data. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public final byte[] data = new byte[64];
|
||||
|
||||
/** The length of the data received (0-8 bytes). */
|
||||
@SuppressWarnings("MemberName")
|
||||
public int length;
|
||||
|
||||
/** The flags of the message. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public int flags;
|
||||
|
||||
/** Timestamp message was received, in microseconds (wpi time). */
|
||||
@SuppressWarnings("MemberName")
|
||||
public long timestamp;
|
||||
|
||||
/** Default constructor. */
|
||||
public CANReceiveMessage() {}
|
||||
|
||||
/**
|
||||
* API used from JNI to set the data.
|
||||
*
|
||||
* @param length Length of packet in bytes.
|
||||
* @param flags Message flags.
|
||||
* @param timestamp CAN frame timestamp in microseconds.
|
||||
* @return Buffer containing CAN frame.
|
||||
*/
|
||||
@SuppressWarnings("PMD.MethodReturnsInternalArray")
|
||||
public byte[] setReceiveData(int length, int flags, long timestamp) {
|
||||
this.flags = flags;
|
||||
this.length = length;
|
||||
this.timestamp = timestamp;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.hal;
|
||||
package edu.wpi.first.hal.can;
|
||||
|
||||
/** Represents a CAN message read from a stream. */
|
||||
public class CANStreamMessage {
|
||||
@@ -14,13 +14,17 @@ public class CANStreamMessage {
|
||||
@SuppressWarnings("MemberName")
|
||||
public int length;
|
||||
|
||||
/** The flags of the message. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public int flags;
|
||||
|
||||
/** Timestamp message was received, in milliseconds (based off of CLOCK_MONOTONIC). */
|
||||
@SuppressWarnings("MemberName")
|
||||
public long timestamp;
|
||||
|
||||
/** The message ID. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public int messageID;
|
||||
public int messageId;
|
||||
|
||||
/** Default constructor. */
|
||||
public CANStreamMessage() {}
|
||||
@@ -29,13 +33,15 @@ public class CANStreamMessage {
|
||||
* API used from JNI to set the data.
|
||||
*
|
||||
* @param length Length of packet in bytes.
|
||||
* @param messageID CAN message ID of the message.
|
||||
* @param messageId CAN message ID of the message.
|
||||
* @param flags Message flags.
|
||||
* @param timestamp CAN frame timestamp in microseconds.
|
||||
* @return Buffer containing CAN frame.
|
||||
*/
|
||||
@SuppressWarnings("PMD.MethodReturnsInternalArray")
|
||||
public byte[] setStreamData(int length, int messageID, long timestamp) {
|
||||
this.messageID = messageID;
|
||||
public byte[] setStreamData(int length, int flags, int messageId, long timestamp) {
|
||||
this.messageId = messageId;
|
||||
this.flags = flags;
|
||||
this.length = length;
|
||||
this.timestamp = timestamp;
|
||||
return data;
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
package edu.wpi.first.hal.can;
|
||||
|
||||
import edu.wpi.first.hal.CANStreamMessage;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@@ -11,10 +12,10 @@
|
||||
|
||||
namespace hal {
|
||||
struct CANTestStore {
|
||||
CANTestStore(int32_t deviceId, int32_t* status) {
|
||||
CANTestStore(int32_t busId, int32_t deviceId, int32_t* status) {
|
||||
this->deviceId = deviceId;
|
||||
handle = HAL_InitializeCAN(
|
||||
HAL_CANManufacturer::HAL_CAN_Man_kTeamUse, deviceId,
|
||||
busId, HAL_CANManufacturer::HAL_CAN_Man_kTeamUse, deviceId,
|
||||
HAL_CANDeviceType::HAL_CAN_Dev_kMiscellaneous, status);
|
||||
}
|
||||
|
||||
@@ -43,28 +44,31 @@ struct CANSendCallbackStore {
|
||||
TEST(CANTest, CanIdPacking) {
|
||||
int32_t status = 0;
|
||||
int32_t deviceId = 12;
|
||||
CANTestStore testStore(deviceId, &status);
|
||||
CANTestStore testStore(0, deviceId, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
std::pair<int32_t, bool> storePair;
|
||||
storePair.second = false;
|
||||
|
||||
auto cbHandle = HALSIM_RegisterCanSendMessageCallback(
|
||||
[](const char* name, void* param, uint32_t messageID, const uint8_t* data,
|
||||
uint8_t dataSize, int32_t periodMs, int32_t* status) {
|
||||
[](const char* name, void* param, int32_t busId, uint32_t messageId,
|
||||
const struct HAL_CANMessage* message, int32_t periodMs,
|
||||
int32_t* status) {
|
||||
std::pair<int32_t, bool>* paramI =
|
||||
reinterpret_cast<std::pair<int32_t, bool>*>(param);
|
||||
paramI->first = messageID;
|
||||
paramI->first = messageId;
|
||||
paramI->second = true;
|
||||
},
|
||||
&storePair);
|
||||
|
||||
CANSendCallbackStore cbStore(cbHandle);
|
||||
uint8_t data[8];
|
||||
HAL_CANMessage message;
|
||||
std::memset(&message, 0, sizeof(message));
|
||||
message.dataSize = 8;
|
||||
|
||||
int32_t apiId = 42;
|
||||
|
||||
HAL_WriteCANPacket(testStore.handle, data, 8, 42, &status);
|
||||
HAL_WriteCANPacket(testStore.handle, apiId, &message, &status);
|
||||
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ TEST(PCMDataTest, PCMInitialization) {
|
||||
// Use out of range index
|
||||
module = 8000;
|
||||
gTestSolenoidCallbackName = "Unset";
|
||||
pcmHandle = HAL_InitializeCTREPCM(module, nullptr, &status);
|
||||
pcmHandle = HAL_InitializeCTREPCM(0, module, nullptr, &status);
|
||||
EXPECT_EQ(HAL_kInvalidHandle, pcmHandle);
|
||||
EXPECT_EQ(HAL_USE_LAST_ERROR, status);
|
||||
HAL_GetLastError(&status);
|
||||
@@ -49,7 +49,7 @@ TEST(PCMDataTest, PCMInitialization) {
|
||||
status = 0;
|
||||
module = MODULE_TO_TEST;
|
||||
gTestSolenoidCallbackName = "Unset";
|
||||
pcmHandle = HAL_InitializeCTREPCM(module, nullptr, &status);
|
||||
pcmHandle = HAL_InitializeCTREPCM(0, module, nullptr, &status);
|
||||
EXPECT_TRUE(HAL_kInvalidHandle != pcmHandle);
|
||||
EXPECT_EQ(0, status);
|
||||
EXPECT_STREQ("Initialized", gTestSolenoidCallbackName.c_str());
|
||||
@@ -58,7 +58,7 @@ TEST(PCMDataTest, PCMInitialization) {
|
||||
status = 0;
|
||||
module = MODULE_TO_TEST;
|
||||
gTestSolenoidCallbackName = "Unset";
|
||||
pcmHandle = HAL_InitializeCTREPCM(module, nullptr, &status);
|
||||
pcmHandle = HAL_InitializeCTREPCM(0, module, nullptr, &status);
|
||||
EXPECT_EQ(HAL_kInvalidHandle, pcmHandle);
|
||||
EXPECT_EQ(HAL_USE_LAST_ERROR, status);
|
||||
HAL_GetLastError(&status);
|
||||
@@ -76,7 +76,7 @@ TEST(PCMDataTest, PCMInitialization) {
|
||||
status = 0;
|
||||
module = MODULE_TO_TEST;
|
||||
gTestSolenoidCallbackName = "Unset";
|
||||
pcmHandle = HAL_InitializeCTREPCM(module, nullptr, &status);
|
||||
pcmHandle = HAL_InitializeCTREPCM(0, module, nullptr, &status);
|
||||
EXPECT_TRUE(HAL_kInvalidHandle != pcmHandle);
|
||||
EXPECT_EQ(0, status);
|
||||
EXPECT_STREQ("Initialized", gTestSolenoidCallbackName.c_str());
|
||||
|
||||
@@ -33,7 +33,7 @@ TEST(PdpSimTest, PdpInitialization) {
|
||||
// Use out of range index
|
||||
gTestPdpCallbackName = "Unset";
|
||||
HAL_InitializePowerDistribution(
|
||||
INDEX_TO_TEST, HAL_PowerDistributionType_kCTRE, nullptr, &status);
|
||||
0, INDEX_TO_TEST, HAL_PowerDistributionType_kCTRE, nullptr, &status);
|
||||
EXPECT_EQ(0, status);
|
||||
EXPECT_STREQ("Initialized", gTestPdpCallbackName.c_str());
|
||||
}
|
||||
|
||||
@@ -15,12 +15,13 @@
|
||||
|
||||
using namespace frc;
|
||||
|
||||
CAN::CAN(int deviceId) : CAN{kTeamManufacturer, deviceId, kTeamDeviceType} {}
|
||||
CAN::CAN(int busId, int deviceId)
|
||||
: CAN{busId, deviceId, kTeamManufacturer, kTeamDeviceType} {}
|
||||
|
||||
CAN::CAN(int deviceId, int deviceManufacturer, int deviceType) {
|
||||
CAN::CAN(int busId, int deviceId, int deviceManufacturer, int deviceType) {
|
||||
int32_t status = 0;
|
||||
m_handle = HAL_InitializeCAN(
|
||||
static_cast<HAL_CANManufacturer>(deviceManufacturer), deviceId,
|
||||
busId, static_cast<HAL_CANManufacturer>(deviceManufacturer), deviceId,
|
||||
static_cast<HAL_CANDeviceType>(deviceType), &status);
|
||||
FRC_CheckErrorStatus(status, "device id {} mfg {} type {}", deviceId,
|
||||
deviceManufacturer, deviceType);
|
||||
@@ -30,41 +31,41 @@ CAN::CAN(int deviceId, int deviceManufacturer, int deviceType) {
|
||||
"");
|
||||
}
|
||||
|
||||
void CAN::WritePacket(const uint8_t* data, int length, int apiId) {
|
||||
void CAN::WritePacket(int apiId, const HAL_CANMessage& message) {
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacket(m_handle, data, length, apiId, &status);
|
||||
HAL_WriteCANPacket(m_handle, apiId, &message, &status);
|
||||
FRC_CheckErrorStatus(status, "WritePacket");
|
||||
}
|
||||
|
||||
void CAN::WritePacketRepeating(const uint8_t* data, int length, int apiId,
|
||||
void CAN::WritePacketRepeating(int apiId, const HAL_CANMessage& message,
|
||||
int repeatMs) {
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacketRepeating(m_handle, data, length, apiId, repeatMs, &status);
|
||||
HAL_WriteCANPacketRepeating(m_handle, apiId, &message, repeatMs, &status);
|
||||
FRC_CheckErrorStatus(status, "WritePacketRepeating");
|
||||
}
|
||||
|
||||
void CAN::WriteRTRFrame(int length, int apiId) {
|
||||
void CAN::WriteRTRFrame(int apiId, const HAL_CANMessage& message) {
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANRTRFrame(m_handle, length, apiId, &status);
|
||||
HAL_WriteCANRTRFrame(m_handle, apiId, &message, &status);
|
||||
FRC_CheckErrorStatus(status, "WriteRTRFrame");
|
||||
}
|
||||
|
||||
int CAN::WritePacketNoError(const uint8_t* data, int length, int apiId) {
|
||||
int CAN::WritePacketNoError(int apiId, const HAL_CANMessage& message) {
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacket(m_handle, data, length, apiId, &status);
|
||||
HAL_WriteCANPacket(m_handle, apiId, &message, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
int CAN::WritePacketRepeatingNoError(const uint8_t* data, int length, int apiId,
|
||||
int CAN::WritePacketRepeatingNoError(int apiId, const HAL_CANMessage& message,
|
||||
int repeatMs) {
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacketRepeating(m_handle, data, length, apiId, repeatMs, &status);
|
||||
HAL_WriteCANPacketRepeating(m_handle, apiId, &message, repeatMs, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
int CAN::WriteRTRFrameNoError(int length, int apiId) {
|
||||
int CAN::WriteRTRFrameNoError(int apiId, const HAL_CANMessage& message) {
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANRTRFrame(m_handle, length, apiId, &status);
|
||||
HAL_WriteCANRTRFrame(m_handle, apiId, &message, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -74,10 +75,9 @@ void CAN::StopPacketRepeating(int apiId) {
|
||||
FRC_CheckErrorStatus(status, "StopPacketRepeating");
|
||||
}
|
||||
|
||||
bool CAN::ReadPacketNew(int apiId, CANData* data) {
|
||||
bool CAN::ReadPacketNew(int apiId, HAL_CANReceiveMessage* data) {
|
||||
int32_t status = 0;
|
||||
HAL_ReadCANPacketNew(m_handle, apiId, data->data, &data->length,
|
||||
&data->timestamp, &status);
|
||||
HAL_ReadCANPacketNew(m_handle, apiId, data, &status);
|
||||
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
|
||||
return false;
|
||||
}
|
||||
@@ -89,10 +89,9 @@ bool CAN::ReadPacketNew(int apiId, CANData* data) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CAN::ReadPacketLatest(int apiId, CANData* data) {
|
||||
bool CAN::ReadPacketLatest(int apiId, HAL_CANReceiveMessage* data) {
|
||||
int32_t status = 0;
|
||||
HAL_ReadCANPacketLatest(m_handle, apiId, data->data, &data->length,
|
||||
&data->timestamp, &status);
|
||||
HAL_ReadCANPacketLatest(m_handle, apiId, data, &status);
|
||||
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
|
||||
return false;
|
||||
}
|
||||
@@ -104,10 +103,10 @@ bool CAN::ReadPacketLatest(int apiId, CANData* data) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CAN::ReadPacketTimeout(int apiId, int timeoutMs, CANData* data) {
|
||||
bool CAN::ReadPacketTimeout(int apiId, int timeoutMs,
|
||||
HAL_CANReceiveMessage* data) {
|
||||
int32_t status = 0;
|
||||
HAL_ReadCANPacketTimeout(m_handle, apiId, data->data, &data->length,
|
||||
&data->timestamp, timeoutMs, &status);
|
||||
HAL_ReadCANPacketTimeout(m_handle, apiId, data, timeoutMs, &status);
|
||||
if (status == HAL_CAN_TIMEOUT ||
|
||||
status == HAL_ERR_CANSessionMux_MessageNotFound) {
|
||||
return false;
|
||||
@@ -119,7 +118,3 @@ bool CAN::ReadPacketTimeout(int apiId, int timeoutMs, CANData* data) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t CAN::GetTimestampBaseTime() {
|
||||
return HAL_GetCANPacketBaseTime();
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
using namespace frc;
|
||||
|
||||
Compressor::Compressor(int module, PneumaticsModuleType moduleType)
|
||||
: m_module{PneumaticsBase::GetForType(module, moduleType)},
|
||||
Compressor::Compressor(int busId, int module, PneumaticsModuleType moduleType)
|
||||
: m_module{PneumaticsBase::GetForType(busId, module, moduleType)},
|
||||
m_moduleType{moduleType} {
|
||||
if (!m_module->ReserveCompressor()) {
|
||||
throw FRC_MakeError(err::ResourceAlreadyAllocated, "{}", module);
|
||||
@@ -27,8 +27,9 @@ Compressor::Compressor(int module, PneumaticsModuleType moduleType)
|
||||
wpi::SendableRegistry::Add(this, "Compressor", module);
|
||||
}
|
||||
|
||||
Compressor::Compressor(PneumaticsModuleType moduleType)
|
||||
: Compressor{PneumaticsBase::GetDefaultForType(moduleType), moduleType} {}
|
||||
Compressor::Compressor(int busId, PneumaticsModuleType moduleType)
|
||||
: Compressor{busId, PneumaticsBase::GetDefaultForType(moduleType),
|
||||
moduleType} {}
|
||||
|
||||
Compressor::~Compressor() {
|
||||
if (m_module) {
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
|
||||
using namespace frc;
|
||||
|
||||
DoubleSolenoid::DoubleSolenoid(int module, PneumaticsModuleType moduleType,
|
||||
DoubleSolenoid::DoubleSolenoid(int busId, int module,
|
||||
PneumaticsModuleType moduleType,
|
||||
int forwardChannel, int reverseChannel)
|
||||
: m_module{PneumaticsBase::GetForType(module, moduleType)},
|
||||
: m_module{PneumaticsBase::GetForType(busId, module, moduleType)},
|
||||
m_forwardChannel{forwardChannel},
|
||||
m_reverseChannel{reverseChannel} {
|
||||
if (!m_module->CheckSolenoidChannel(m_forwardChannel)) {
|
||||
@@ -56,10 +57,10 @@ DoubleSolenoid::DoubleSolenoid(int module, PneumaticsModuleType moduleType,
|
||||
m_module->GetModuleNumber(), m_forwardChannel);
|
||||
}
|
||||
|
||||
DoubleSolenoid::DoubleSolenoid(PneumaticsModuleType moduleType,
|
||||
DoubleSolenoid::DoubleSolenoid(int busId, PneumaticsModuleType moduleType,
|
||||
int forwardChannel, int reverseChannel)
|
||||
: DoubleSolenoid{PneumaticsBase::GetDefaultForType(moduleType), moduleType,
|
||||
forwardChannel, reverseChannel} {}
|
||||
: DoubleSolenoid{busId, PneumaticsBase::GetDefaultForType(moduleType),
|
||||
moduleType, forwardChannel, reverseChannel} {}
|
||||
|
||||
DoubleSolenoid::~DoubleSolenoid() {
|
||||
if (m_module) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <string>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <hal/Ports.h>
|
||||
#include <hal/REVPH.h>
|
||||
#include <hal/UsageReporting.h>
|
||||
#include <wpi/NullDeleter.h>
|
||||
@@ -39,26 +40,31 @@ units::volt_t PSIToVolts(units::pounds_per_square_inch_t pressure,
|
||||
}
|
||||
|
||||
wpi::mutex PneumaticHub::m_handleLock;
|
||||
std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>>
|
||||
PneumaticHub::m_handleMap = nullptr;
|
||||
std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>[]>
|
||||
PneumaticHub::m_handleMaps = nullptr;
|
||||
|
||||
// Always called under lock, so we can avoid the double lock from the magic
|
||||
// static
|
||||
std::weak_ptr<PneumaticHub::DataStore>& PneumaticHub::GetDataStore(int module) {
|
||||
if (!m_handleMap) {
|
||||
m_handleMap = std::make_unique<
|
||||
wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>>();
|
||||
std::weak_ptr<PneumaticHub::DataStore>& PneumaticHub::GetDataStore(int busId,
|
||||
int module) {
|
||||
int32_t numBuses = HAL_GetNumCanBuses();
|
||||
FRC_AssertMessage(busId >= 0 && busId < numBuses,
|
||||
"Bus {} out of range. Must be [0-{}).", busId, numBuses);
|
||||
if (!m_handleMaps) {
|
||||
m_handleMaps = std::make_unique<
|
||||
wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>[]>(numBuses);
|
||||
}
|
||||
return (*m_handleMap)[module];
|
||||
return m_handleMaps[busId][module];
|
||||
}
|
||||
|
||||
class PneumaticHub::DataStore {
|
||||
public:
|
||||
explicit DataStore(int module, const char* stackTrace) {
|
||||
explicit DataStore(int busId, int module, const char* stackTrace) {
|
||||
int32_t status = 0;
|
||||
HAL_REVPHHandle handle = HAL_InitializeREVPH(module, stackTrace, &status);
|
||||
HAL_REVPHHandle handle =
|
||||
HAL_InitializeREVPH(busId, module, stackTrace, &status);
|
||||
FRC_CheckErrorStatus(status, "Module {}", module);
|
||||
m_moduleObject = PneumaticHub{handle, module};
|
||||
m_moduleObject = PneumaticHub{busId, handle, module};
|
||||
m_moduleObject.m_dataStore =
|
||||
std::shared_ptr<DataStore>{this, wpi::NullDeleter<DataStore>()};
|
||||
|
||||
@@ -105,27 +111,28 @@ class PneumaticHub::DataStore {
|
||||
uint32_t m_reservedMask{0};
|
||||
bool m_compressorReserved{false};
|
||||
wpi::mutex m_reservedLock;
|
||||
PneumaticHub m_moduleObject{HAL_kInvalidHandle, 0};
|
||||
PneumaticHub m_moduleObject{0, HAL_kInvalidHandle, 0};
|
||||
std::array<units::millisecond_t, 16> m_oneShotDurMs{0_ms};
|
||||
};
|
||||
|
||||
PneumaticHub::PneumaticHub()
|
||||
: PneumaticHub{SensorUtil::GetDefaultREVPHModule()} {}
|
||||
PneumaticHub::PneumaticHub(int busId)
|
||||
: PneumaticHub{busId, SensorUtil::GetDefaultREVPHModule()} {}
|
||||
|
||||
PneumaticHub::PneumaticHub(int module) {
|
||||
PneumaticHub::PneumaticHub(int busId, int module) {
|
||||
std::string stackTrace = wpi::GetStackTrace(1);
|
||||
std::scoped_lock lock(m_handleLock);
|
||||
auto& res = GetDataStore(module);
|
||||
auto& res = GetDataStore(busId, module);
|
||||
m_dataStore = res.lock();
|
||||
if (!m_dataStore) {
|
||||
m_dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
|
||||
m_dataStore =
|
||||
std::make_shared<DataStore>(busId, module, stackTrace.c_str());
|
||||
res = m_dataStore;
|
||||
}
|
||||
m_handle = m_dataStore->m_moduleObject.m_handle;
|
||||
m_module = module;
|
||||
}
|
||||
|
||||
PneumaticHub::PneumaticHub(HAL_REVPHHandle handle, int module)
|
||||
PneumaticHub::PneumaticHub(int /* busId */, HAL_REVPHHandle handle, int module)
|
||||
: m_handle{handle}, m_module{module} {}
|
||||
|
||||
bool PneumaticHub::GetCompressor() const {
|
||||
@@ -446,13 +453,14 @@ void PneumaticHub::ReportUsage(std::string_view device, std::string_view data) {
|
||||
HAL_ReportUsage(fmt::format("PH[{}]/{}", m_module, device), data);
|
||||
}
|
||||
|
||||
std::shared_ptr<PneumaticsBase> PneumaticHub::GetForModule(int module) {
|
||||
std::shared_ptr<PneumaticsBase> PneumaticHub::GetForModule(int busId,
|
||||
int module) {
|
||||
std::string stackTrace = wpi::GetStackTrace(1);
|
||||
std::scoped_lock lock(m_handleLock);
|
||||
auto& res = GetDataStore(module);
|
||||
auto& res = GetDataStore(busId, module);
|
||||
std::shared_ptr<DataStore> dataStore = res.lock();
|
||||
if (!dataStore) {
|
||||
dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
|
||||
dataStore = std::make_shared<DataStore>(busId, module, stackTrace.c_str());
|
||||
res = dataStore;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ static_assert(
|
||||
HAL_REVPHCompressorConfigType::HAL_REVPHCompressorConfigType_kHybrid);
|
||||
|
||||
std::shared_ptr<PneumaticsBase> PneumaticsBase::GetForType(
|
||||
int module, PneumaticsModuleType moduleType) {
|
||||
int busId, int module, PneumaticsModuleType moduleType) {
|
||||
if (moduleType == PneumaticsModuleType::CTREPCM) {
|
||||
return PneumaticsControlModule::GetForModule(module);
|
||||
return PneumaticsControlModule::GetForModule(busId, module);
|
||||
} else if (moduleType == PneumaticsModuleType::REVPH) {
|
||||
return PneumaticHub::GetForModule(module);
|
||||
return PneumaticHub::GetForModule(busId, module);
|
||||
}
|
||||
throw FRC_MakeError(err::InvalidParameter, "{}",
|
||||
static_cast<int>(moduleType));
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <hal/CTREPCM.h>
|
||||
#include <hal/Ports.h>
|
||||
#include <hal/UsageReporting.h>
|
||||
#include <wpi/NullDeleter.h>
|
||||
#include <wpi/StackTrace.h>
|
||||
@@ -23,28 +24,32 @@ using namespace frc;
|
||||
|
||||
wpi::mutex PneumaticsControlModule::m_handleLock;
|
||||
std::unique_ptr<
|
||||
wpi::DenseMap<int, std::weak_ptr<PneumaticsControlModule::DataStore>>>
|
||||
PneumaticsControlModule::m_handleMap = nullptr;
|
||||
wpi::DenseMap<int, std::weak_ptr<PneumaticsControlModule::DataStore>>[]>
|
||||
PneumaticsControlModule::m_handleMaps = nullptr;
|
||||
|
||||
// Always called under lock, so we can avoid the double lock from the magic
|
||||
// static
|
||||
std::weak_ptr<PneumaticsControlModule::DataStore>&
|
||||
PneumaticsControlModule::GetDataStore(int module) {
|
||||
if (!m_handleMap) {
|
||||
m_handleMap = std::make_unique<wpi::DenseMap<
|
||||
int, std::weak_ptr<PneumaticsControlModule::DataStore>>>();
|
||||
PneumaticsControlModule::GetDataStore(int busId, int module) {
|
||||
int32_t numBuses = HAL_GetNumCanBuses();
|
||||
FRC_AssertMessage(busId >= 0 && busId < numBuses,
|
||||
"Bus {} out of range. Must be [0-{}).", busId, numBuses);
|
||||
if (!m_handleMaps) {
|
||||
m_handleMaps = std::make_unique<wpi::DenseMap<
|
||||
int, std::weak_ptr<PneumaticsControlModule::DataStore>>[]>(numBuses);
|
||||
}
|
||||
return (*m_handleMap)[module];
|
||||
|
||||
return m_handleMaps[busId][module];
|
||||
}
|
||||
|
||||
class PneumaticsControlModule::DataStore {
|
||||
public:
|
||||
explicit DataStore(int module, const char* stackTrace) {
|
||||
explicit DataStore(int busId, int module, const char* stackTrace) {
|
||||
int32_t status = 0;
|
||||
HAL_CTREPCMHandle handle =
|
||||
HAL_InitializeCTREPCM(module, stackTrace, &status);
|
||||
HAL_InitializeCTREPCM(busId, module, stackTrace, &status);
|
||||
FRC_CheckErrorStatus(status, "Module {}", module);
|
||||
m_moduleObject = PneumaticsControlModule{handle, module};
|
||||
m_moduleObject = PneumaticsControlModule{busId, handle, module};
|
||||
m_moduleObject.m_dataStore =
|
||||
std::shared_ptr<DataStore>{this, wpi::NullDeleter<DataStore>()};
|
||||
}
|
||||
@@ -59,26 +64,28 @@ class PneumaticsControlModule::DataStore {
|
||||
uint32_t m_reservedMask{0};
|
||||
bool m_compressorReserved{false};
|
||||
wpi::mutex m_reservedLock;
|
||||
PneumaticsControlModule m_moduleObject{HAL_kInvalidHandle, 0};
|
||||
PneumaticsControlModule m_moduleObject{0, HAL_kInvalidHandle, 0};
|
||||
};
|
||||
|
||||
PneumaticsControlModule::PneumaticsControlModule()
|
||||
: PneumaticsControlModule{SensorUtil::GetDefaultCTREPCMModule()} {}
|
||||
PneumaticsControlModule::PneumaticsControlModule(int busId)
|
||||
: PneumaticsControlModule{busId, SensorUtil::GetDefaultCTREPCMModule()} {}
|
||||
|
||||
PneumaticsControlModule::PneumaticsControlModule(int module) {
|
||||
PneumaticsControlModule::PneumaticsControlModule(int busId, int module) {
|
||||
std::string stackTrace = wpi::GetStackTrace(1);
|
||||
std::scoped_lock lock(m_handleLock);
|
||||
auto& res = GetDataStore(module);
|
||||
auto& res = GetDataStore(busId, module);
|
||||
m_dataStore = res.lock();
|
||||
if (!m_dataStore) {
|
||||
m_dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
|
||||
m_dataStore =
|
||||
std::make_shared<DataStore>(busId, module, stackTrace.c_str());
|
||||
res = m_dataStore;
|
||||
}
|
||||
m_handle = m_dataStore->m_moduleObject.m_handle;
|
||||
m_module = module;
|
||||
}
|
||||
|
||||
PneumaticsControlModule::PneumaticsControlModule(HAL_CTREPCMHandle handle,
|
||||
PneumaticsControlModule::PneumaticsControlModule(int /* busId */,
|
||||
HAL_CTREPCMHandle handle,
|
||||
int module)
|
||||
: m_handle{handle}, m_module{module} {}
|
||||
|
||||
@@ -297,13 +304,13 @@ void PneumaticsControlModule::ReportUsage(std::string_view device,
|
||||
}
|
||||
|
||||
std::shared_ptr<PneumaticsBase> PneumaticsControlModule::GetForModule(
|
||||
int module) {
|
||||
int busId, int module) {
|
||||
std::string stackTrace = wpi::GetStackTrace(1);
|
||||
std::scoped_lock lock(m_handleLock);
|
||||
auto& res = GetDataStore(module);
|
||||
auto& res = GetDataStore(busId, module);
|
||||
std::shared_ptr<DataStore> dataStore = res.lock();
|
||||
if (!dataStore) {
|
||||
dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
|
||||
dataStore = std::make_shared<DataStore>(busId, module, stackTrace.c_str());
|
||||
res = dataStore;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,12 +27,12 @@ static_assert(frc::PowerDistribution::kDefaultModule ==
|
||||
|
||||
using namespace frc;
|
||||
|
||||
PowerDistribution::PowerDistribution() {
|
||||
PowerDistribution::PowerDistribution(int busId) {
|
||||
auto stack = wpi::GetStackTrace(1);
|
||||
|
||||
int32_t status = 0;
|
||||
m_handle = HAL_InitializePowerDistribution(
|
||||
kDefaultModule,
|
||||
busId, kDefaultModule,
|
||||
HAL_PowerDistributionType::HAL_PowerDistributionType_kAutomatic,
|
||||
stack.c_str(), &status);
|
||||
FRC_CheckErrorStatus(status, "Module {}", kDefaultModule);
|
||||
@@ -48,13 +48,14 @@ PowerDistribution::PowerDistribution() {
|
||||
wpi::SendableRegistry::Add(this, "PowerDistribution", m_module);
|
||||
}
|
||||
|
||||
PowerDistribution::PowerDistribution(int module, ModuleType moduleType) {
|
||||
PowerDistribution::PowerDistribution(int busId, int module,
|
||||
ModuleType moduleType) {
|
||||
auto stack = wpi::GetStackTrace(1);
|
||||
|
||||
int32_t status = 0;
|
||||
m_handle = HAL_InitializePowerDistribution(
|
||||
module, static_cast<HAL_PowerDistributionType>(moduleType), stack.c_str(),
|
||||
&status);
|
||||
busId, module, static_cast<HAL_PowerDistributionType>(moduleType),
|
||||
stack.c_str(), &status);
|
||||
FRC_CheckErrorStatus(status, "Module {}", module);
|
||||
m_module = HAL_GetPowerDistributionModuleNumber(m_handle, &status);
|
||||
FRC_ReportError(status, "Module {}", module);
|
||||
|
||||
@@ -284,15 +284,16 @@ RadioLEDState RobotController::GetRadioLEDState() {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
CANStatus RobotController::GetCANStatus() {
|
||||
CANStatus RobotController::GetCANStatus(int busId) {
|
||||
int32_t status = 0;
|
||||
float percentBusUtilization = 0;
|
||||
uint32_t busOffCount = 0;
|
||||
uint32_t txFullCount = 0;
|
||||
uint32_t receiveErrorCount = 0;
|
||||
uint32_t transmitErrorCount = 0;
|
||||
HAL_CAN_GetCANStatus(&percentBusUtilization, &busOffCount, &txFullCount,
|
||||
&receiveErrorCount, &transmitErrorCount, &status);
|
||||
HAL_CAN_GetCANStatus(busId, &percentBusUtilization, &busOffCount,
|
||||
&txFullCount, &receiveErrorCount, &transmitErrorCount,
|
||||
&status);
|
||||
FRC_CheckErrorStatus(status, "GetCANStatus");
|
||||
return {percentBusUtilization, static_cast<int>(busOffCount),
|
||||
static_cast<int>(txFullCount), static_cast<int>(receiveErrorCount),
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
|
||||
using namespace frc;
|
||||
|
||||
Solenoid::Solenoid(int module, PneumaticsModuleType moduleType, int channel)
|
||||
: m_module{PneumaticsBase::GetForType(module, moduleType)},
|
||||
Solenoid::Solenoid(int busId, int module, PneumaticsModuleType moduleType,
|
||||
int channel)
|
||||
: m_module{PneumaticsBase::GetForType(busId, module, moduleType)},
|
||||
m_channel{channel} {
|
||||
if (!m_module->CheckSolenoidChannel(m_channel)) {
|
||||
throw FRC_MakeError(err::ChannelIndexOutOfRange, "Channel {}", m_channel);
|
||||
@@ -32,8 +33,8 @@ Solenoid::Solenoid(int module, PneumaticsModuleType moduleType, int channel)
|
||||
m_channel);
|
||||
}
|
||||
|
||||
Solenoid::Solenoid(PneumaticsModuleType moduleType, int channel)
|
||||
: Solenoid{PneumaticsBase::GetDefaultForType(moduleType), moduleType,
|
||||
Solenoid::Solenoid(int busId, PneumaticsModuleType moduleType, int channel)
|
||||
: Solenoid{busId, PneumaticsBase::GetDefaultForType(moduleType), moduleType,
|
||||
channel} {}
|
||||
|
||||
Solenoid::~Solenoid() {
|
||||
|
||||
@@ -9,14 +9,6 @@
|
||||
#include <hal/CANAPI.h>
|
||||
|
||||
namespace frc {
|
||||
struct CANData {
|
||||
/** Contents of the CAN packet. */
|
||||
uint8_t data[8];
|
||||
/** Length of packet in bytes. */
|
||||
int32_t length;
|
||||
/** CAN frame timestamp in milliseconds. */
|
||||
uint64_t timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
* High level class for interfacing with CAN devices conforming to
|
||||
@@ -35,20 +27,22 @@ class CAN {
|
||||
* This uses the team manufacturer and device types.
|
||||
* The device ID is 6 bits (0-63)
|
||||
*
|
||||
* @param busId The bus id
|
||||
* @param deviceId The device id
|
||||
*/
|
||||
explicit CAN(int deviceId);
|
||||
CAN(int busId, int deviceId);
|
||||
|
||||
/**
|
||||
* Create a new CAN communication interface with a specific device ID,
|
||||
* manufacturer and device type. The device ID is 6 bits, the
|
||||
* manufacturer is 8 bits, and the device type is 5 bits.
|
||||
*
|
||||
* @param busId The bus id
|
||||
* @param deviceId The device ID
|
||||
* @param deviceManufacturer The device manufacturer
|
||||
* @param deviceType The device type
|
||||
*/
|
||||
CAN(int deviceId, int deviceManufacturer, int deviceType);
|
||||
CAN(int busId, int deviceId, int deviceManufacturer, int deviceType);
|
||||
|
||||
CAN(CAN&&) = default;
|
||||
CAN& operator=(CAN&&) = default;
|
||||
@@ -56,23 +50,21 @@ class CAN {
|
||||
/**
|
||||
* Write a packet to the CAN device with a specific ID. This ID is 10 bits.
|
||||
*
|
||||
* @param data The data to write (8 bytes max)
|
||||
* @param length The data length to write
|
||||
* @param apiId The API ID to write.
|
||||
* @param message the CAN message.
|
||||
*/
|
||||
void WritePacket(const uint8_t* data, int length, int apiId);
|
||||
void WritePacket(int apiId, const HAL_CANMessage& message);
|
||||
|
||||
/**
|
||||
* Write 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
|
||||
*
|
||||
* @param data The data to write (8 bytes max)
|
||||
* @param length The data length to write
|
||||
* @param apiId The API ID to write.
|
||||
* @param message the CAN message.
|
||||
* @param repeatMs The period to repeat the packet at.
|
||||
*/
|
||||
void WritePacketRepeating(const uint8_t* data, int length, int apiId,
|
||||
void WritePacketRepeating(int apiId, const HAL_CANMessage& message,
|
||||
int repeatMs);
|
||||
|
||||
/**
|
||||
@@ -80,31 +72,29 @@ class CAN {
|
||||
* bits. The length by spec must match what is returned by the responding
|
||||
* device
|
||||
*
|
||||
* @param length The length to request (0 to 8)
|
||||
* @param apiId The API ID to write.
|
||||
* @param message the CAN message.
|
||||
*/
|
||||
void WriteRTRFrame(int length, int apiId);
|
||||
void WriteRTRFrame(int apiId, const HAL_CANMessage& message);
|
||||
|
||||
/**
|
||||
* Write a packet to the CAN device with a specific ID. This ID is 10 bits.
|
||||
*
|
||||
* @param data The data to write (8 bytes max)
|
||||
* @param length The data length to write
|
||||
* @param apiId The API ID to write.
|
||||
* @param message the CAN message.
|
||||
*/
|
||||
int WritePacketNoError(const uint8_t* data, int length, int apiId);
|
||||
int WritePacketNoError(int apiId, const HAL_CANMessage& message);
|
||||
|
||||
/**
|
||||
* Write 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
|
||||
*
|
||||
* @param data The data to write (8 bytes max)
|
||||
* @param length The data length to write
|
||||
* @param apiId The API ID to write.
|
||||
* @param message the CAN message.
|
||||
* @param repeatMs The period to repeat the packet at.
|
||||
*/
|
||||
int WritePacketRepeatingNoError(const uint8_t* data, int length, int apiId,
|
||||
int WritePacketRepeatingNoError(int apiId, const HAL_CANMessage& message,
|
||||
int repeatMs);
|
||||
|
||||
/**
|
||||
@@ -112,10 +102,10 @@ class CAN {
|
||||
* bits. The length by spec must match what is returned by the responding
|
||||
* device
|
||||
*
|
||||
* @param length The length to request (0 to 8)
|
||||
* @param apiId The API ID to write.
|
||||
* @param message the CAN message.
|
||||
*/
|
||||
int WriteRTRFrameNoError(int length, int apiId);
|
||||
int WriteRTRFrameNoError(int apiId, const HAL_CANMessage& message);
|
||||
|
||||
/**
|
||||
* Stop a repeating packet with a specific ID. This ID is 10 bits.
|
||||
@@ -133,7 +123,7 @@ class CAN {
|
||||
* @param data Storage for the received data.
|
||||
* @return True if the data is valid, otherwise false.
|
||||
*/
|
||||
bool ReadPacketNew(int apiId, CANData* data);
|
||||
bool ReadPacketNew(int apiId, HAL_CANReceiveMessage* data);
|
||||
|
||||
/**
|
||||
* Read a CAN packet. The will continuously return the last packet received,
|
||||
@@ -143,7 +133,7 @@ class CAN {
|
||||
* @param data Storage for the received data.
|
||||
* @return True if the data is valid, otherwise false.
|
||||
*/
|
||||
bool ReadPacketLatest(int apiId, CANData* data);
|
||||
bool ReadPacketLatest(int apiId, HAL_CANReceiveMessage* data);
|
||||
|
||||
/**
|
||||
* Read a CAN packet. The will return the last packet received until the
|
||||
@@ -154,16 +144,7 @@ class CAN {
|
||||
* @param data Storage for the received data.
|
||||
* @return True if the data is valid, otherwise false.
|
||||
*/
|
||||
bool ReadPacketTimeout(int apiId, int timeoutMs, CANData* data);
|
||||
|
||||
/**
|
||||
* Reads the current value of the millisecond-resolution timer that CANData
|
||||
* timestamps are based on
|
||||
*
|
||||
* @return Current value of timer used as a base time for CANData timestamps
|
||||
* in milliseconds
|
||||
*/
|
||||
static uint64_t GetTimestampBaseTime();
|
||||
bool ReadPacketTimeout(int apiId, int timeoutMs, HAL_CANReceiveMessage* data);
|
||||
|
||||
/// Team manufacturer.
|
||||
static constexpr HAL_CANManufacturer kTeamManufacturer = HAL_CAN_Man_kTeamUse;
|
||||
|
||||
@@ -37,17 +37,19 @@ class Compressor : public wpi::Sendable,
|
||||
/**
|
||||
* Constructs a compressor for a specified module and type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module The module ID to use.
|
||||
* @param moduleType The module type to use.
|
||||
*/
|
||||
Compressor(int module, PneumaticsModuleType moduleType);
|
||||
Compressor(int busId, int module, PneumaticsModuleType moduleType);
|
||||
|
||||
/**
|
||||
* Constructs a compressor for a default module and specified type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param moduleType The module type to use.
|
||||
*/
|
||||
explicit Compressor(PneumaticsModuleType moduleType);
|
||||
Compressor(int busId, PneumaticsModuleType moduleType);
|
||||
|
||||
~Compressor() override;
|
||||
|
||||
|
||||
@@ -41,23 +41,25 @@ class DoubleSolenoid : public wpi::Sendable,
|
||||
* Constructs a double solenoid for a specified module of a specific module
|
||||
* type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module The module of the solenoid module to use.
|
||||
* @param moduleType The module type to use.
|
||||
* @param forwardChannel The forward channel on the module to control.
|
||||
* @param reverseChannel The reverse channel on the module to control.
|
||||
*/
|
||||
DoubleSolenoid(int module, PneumaticsModuleType moduleType,
|
||||
DoubleSolenoid(int busId, int module, PneumaticsModuleType moduleType,
|
||||
int forwardChannel, int reverseChannel);
|
||||
|
||||
/**
|
||||
* Constructs a double solenoid for a default module of a specific module
|
||||
* type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param moduleType The module type to use.
|
||||
* @param forwardChannel The forward channel on the module to control.
|
||||
* @param reverseChannel The reverse channel on the module to control.
|
||||
*/
|
||||
DoubleSolenoid(PneumaticsModuleType moduleType, int forwardChannel,
|
||||
DoubleSolenoid(int busId, PneumaticsModuleType moduleType, int forwardChannel,
|
||||
int reverseChannel);
|
||||
|
||||
~DoubleSolenoid() override;
|
||||
|
||||
@@ -17,15 +17,20 @@ namespace frc {
|
||||
/** Module class for controlling a REV Robotics Pneumatic Hub. */
|
||||
class PneumaticHub : public PneumaticsBase {
|
||||
public:
|
||||
/** Constructs a PneumaticHub with the default ID (1). */
|
||||
PneumaticHub();
|
||||
/**
|
||||
* Constructs a PneumaticHub with the default ID (1).
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
*/
|
||||
explicit PneumaticHub(int busId);
|
||||
|
||||
/**
|
||||
* Constructs a PneumaticHub.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module module number to construct
|
||||
*/
|
||||
explicit PneumaticHub(int module);
|
||||
PneumaticHub(int busId, int module);
|
||||
|
||||
~PneumaticHub() override = default;
|
||||
|
||||
@@ -296,17 +301,17 @@ class PneumaticHub : public PneumaticsBase {
|
||||
class DataStore;
|
||||
friend class DataStore;
|
||||
friend class PneumaticsBase;
|
||||
PneumaticHub(HAL_REVPHHandle handle, int module);
|
||||
PneumaticHub(int busId, HAL_REVPHHandle handle, int module);
|
||||
|
||||
static std::shared_ptr<PneumaticsBase> GetForModule(int module);
|
||||
static std::shared_ptr<PneumaticsBase> GetForModule(int busId, int module);
|
||||
|
||||
std::shared_ptr<DataStore> m_dataStore;
|
||||
HAL_REVPHHandle m_handle;
|
||||
int m_module;
|
||||
|
||||
static wpi::mutex m_handleLock;
|
||||
static std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<DataStore>>>
|
||||
m_handleMap;
|
||||
static std::weak_ptr<DataStore>& GetDataStore(int module);
|
||||
static std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<DataStore>>[]>
|
||||
m_handleMaps;
|
||||
static std::weak_ptr<DataStore>& GetDataStore(int busId, int module);
|
||||
};
|
||||
} // namespace frc
|
||||
|
||||
@@ -267,12 +267,13 @@ class PneumaticsBase {
|
||||
/**
|
||||
* For internal use to get a module for a specific type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module module number
|
||||
* @param moduleType module type
|
||||
* @return module
|
||||
*/
|
||||
static std::shared_ptr<PneumaticsBase> GetForType(
|
||||
int module, PneumaticsModuleType moduleType);
|
||||
int busId, int module, PneumaticsModuleType moduleType);
|
||||
|
||||
/**
|
||||
* For internal use to get the default for a specific type.
|
||||
|
||||
@@ -17,15 +17,20 @@ namespace frc {
|
||||
* Module. */
|
||||
class PneumaticsControlModule : public PneumaticsBase {
|
||||
public:
|
||||
/** Constructs a PneumaticsControlModule with the default ID (0). */
|
||||
PneumaticsControlModule();
|
||||
/**
|
||||
* Constructs a PneumaticsControlModule with the default ID (0).
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
*/
|
||||
explicit PneumaticsControlModule(int busId);
|
||||
|
||||
/**
|
||||
* Constructs a PneumaticsControlModule.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module module number to construct
|
||||
*/
|
||||
explicit PneumaticsControlModule(int module);
|
||||
PneumaticsControlModule(int busId, int module);
|
||||
|
||||
~PneumaticsControlModule() override = default;
|
||||
|
||||
@@ -196,17 +201,17 @@ class PneumaticsControlModule : public PneumaticsBase {
|
||||
class DataStore;
|
||||
friend class DataStore;
|
||||
friend class PneumaticsBase;
|
||||
PneumaticsControlModule(HAL_CTREPCMHandle handle, int module);
|
||||
PneumaticsControlModule(int busId, HAL_CTREPCMHandle handle, int module);
|
||||
|
||||
static std::shared_ptr<PneumaticsBase> GetForModule(int module);
|
||||
static std::shared_ptr<PneumaticsBase> GetForModule(int busId, int module);
|
||||
|
||||
std::shared_ptr<DataStore> m_dataStore;
|
||||
HAL_CTREPCMHandle m_handle;
|
||||
int m_module;
|
||||
|
||||
static wpi::mutex m_handleLock;
|
||||
static std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<DataStore>>>
|
||||
m_handleMap;
|
||||
static std::weak_ptr<DataStore>& GetDataStore(int module);
|
||||
static std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<DataStore>>[]>
|
||||
m_handleMaps;
|
||||
static std::weak_ptr<DataStore>& GetDataStore(int busId, int module);
|
||||
};
|
||||
} // namespace frc
|
||||
|
||||
@@ -38,16 +38,19 @@ class PowerDistribution : public wpi::Sendable,
|
||||
*
|
||||
* Detects the connected PDP/PDH using the default CAN ID (0 for CTRE and 1
|
||||
* for REV).
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
*/
|
||||
PowerDistribution();
|
||||
explicit PowerDistribution(int busId);
|
||||
|
||||
/**
|
||||
* Constructs a PowerDistribution object.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module The CAN ID of the PDP/PDH
|
||||
* @param moduleType The type of module
|
||||
*/
|
||||
PowerDistribution(int module, ModuleType moduleType);
|
||||
PowerDistribution(int busId, int module, ModuleType moduleType);
|
||||
|
||||
PowerDistribution(PowerDistribution&&) = default;
|
||||
PowerDistribution& operator=(PowerDistribution&&) = default;
|
||||
|
||||
@@ -336,9 +336,10 @@ class RobotController {
|
||||
/**
|
||||
* Get the current status of the CAN bus.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @return The status of the CAN bus
|
||||
*/
|
||||
static CANStatus GetCANStatus();
|
||||
static CANStatus GetCANStatus(int busId);
|
||||
|
||||
private:
|
||||
static std::function<uint64_t()> m_timeSource;
|
||||
|
||||
@@ -28,19 +28,21 @@ class Solenoid : public wpi::Sendable, public wpi::SendableHelper<Solenoid> {
|
||||
/**
|
||||
* Constructs a solenoid for a specified module and type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module The module ID to use.
|
||||
* @param moduleType The module type to use.
|
||||
* @param channel The channel the solenoid is on.
|
||||
*/
|
||||
Solenoid(int module, PneumaticsModuleType moduleType, int channel);
|
||||
Solenoid(int busId, int module, PneumaticsModuleType moduleType, int channel);
|
||||
|
||||
/**
|
||||
* Constructs a solenoid for a default module and specified type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param moduleType The module type to use.
|
||||
* @param channel The channel the solenoid is on.
|
||||
*/
|
||||
Solenoid(PneumaticsModuleType moduleType, int channel);
|
||||
Solenoid(int busId, PneumaticsModuleType moduleType, int channel);
|
||||
|
||||
~Solenoid() override;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace frc {
|
||||
|
||||
TEST(DoubleSolenoidCTRETest, ValidInitialization) {
|
||||
DoubleSolenoid solenoid{3, frc::PneumaticsModuleType::CTREPCM, 2, 3};
|
||||
DoubleSolenoid solenoid{0, 3, frc::PneumaticsModuleType::CTREPCM, 2, 3};
|
||||
solenoid.Set(DoubleSolenoid::kReverse);
|
||||
EXPECT_EQ(DoubleSolenoid::kReverse, solenoid.Get());
|
||||
|
||||
@@ -25,29 +25,29 @@ TEST(DoubleSolenoidCTRETest, ValidInitialization) {
|
||||
|
||||
TEST(DoubleSolenoidCTRETest, ThrowForwardPortAlreadyInitialized) {
|
||||
// Single solenoid that is reused for forward port
|
||||
Solenoid solenoid{5, frc::PneumaticsModuleType::CTREPCM, 2};
|
||||
EXPECT_THROW(DoubleSolenoid(5, frc::PneumaticsModuleType::CTREPCM, 2, 3),
|
||||
Solenoid solenoid{0, 5, frc::PneumaticsModuleType::CTREPCM, 2};
|
||||
EXPECT_THROW(DoubleSolenoid(0, 5, frc::PneumaticsModuleType::CTREPCM, 2, 3),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(DoubleSolenoidCTRETest, ThrowReversePortAlreadyInitialized) {
|
||||
// Single solenoid that is reused for forward port
|
||||
Solenoid solenoid{6, frc::PneumaticsModuleType::CTREPCM, 3};
|
||||
Solenoid solenoid{0, 6, frc::PneumaticsModuleType::CTREPCM, 3};
|
||||
EXPECT_THROW(DoubleSolenoid(6, frc::PneumaticsModuleType::CTREPCM, 2, 3),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(DoubleSolenoidCTRETest, ThrowBothPortsAlreadyInitialized) {
|
||||
PneumaticsControlModule pcm{6};
|
||||
PneumaticsControlModule pcm{0, 6};
|
||||
// Single solenoid that is reused for forward port
|
||||
Solenoid solenoid0(6, frc::PneumaticsModuleType::CTREPCM, 2);
|
||||
Solenoid solenoid1(6, frc::PneumaticsModuleType::CTREPCM, 3);
|
||||
Solenoid solenoid0(0, 6, frc::PneumaticsModuleType::CTREPCM, 2);
|
||||
Solenoid solenoid1(0, 6, frc::PneumaticsModuleType::CTREPCM, 3);
|
||||
EXPECT_THROW(DoubleSolenoid(6, frc::PneumaticsModuleType::CTREPCM, 2, 3),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(DoubleSolenoidCTRETest, Toggle) {
|
||||
DoubleSolenoid solenoid{4, frc::PneumaticsModuleType::CTREPCM, 2, 3};
|
||||
DoubleSolenoid solenoid{0, 4, frc::PneumaticsModuleType::CTREPCM, 2, 3};
|
||||
// Bootstrap it into reverse
|
||||
solenoid.Set(DoubleSolenoid::kReverse);
|
||||
|
||||
@@ -64,12 +64,12 @@ TEST(DoubleSolenoidCTRETest, Toggle) {
|
||||
}
|
||||
|
||||
TEST(DoubleSolenoidCTRETest, InvalidForwardPort) {
|
||||
EXPECT_THROW(DoubleSolenoid(0, frc::PneumaticsModuleType::CTREPCM, 100, 1),
|
||||
EXPECT_THROW(DoubleSolenoid(0, 0, frc::PneumaticsModuleType::CTREPCM, 100, 1),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(DoubleSolenoidCTRETest, InvalidReversePort) {
|
||||
EXPECT_THROW(DoubleSolenoid(0, frc::PneumaticsModuleType::CTREPCM, 0, 100),
|
||||
EXPECT_THROW(DoubleSolenoid(0, 0, frc::PneumaticsModuleType::CTREPCM, 0, 100),
|
||||
std::runtime_error);
|
||||
}
|
||||
} // namespace frc
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace frc {
|
||||
|
||||
TEST(DoubleSolenoidREVTest, ValidInitialization) {
|
||||
DoubleSolenoid solenoid{3, frc::PneumaticsModuleType::CTREPCM, 2, 3};
|
||||
DoubleSolenoid solenoid{0, 3, frc::PneumaticsModuleType::CTREPCM, 2, 3};
|
||||
solenoid.Set(DoubleSolenoid::kReverse);
|
||||
EXPECT_EQ(DoubleSolenoid::kReverse, solenoid.Get());
|
||||
|
||||
@@ -25,29 +25,29 @@ TEST(DoubleSolenoidREVTest, ValidInitialization) {
|
||||
|
||||
TEST(DoubleSolenoidREVTest, ThrowForwardPortAlreadyInitialized) {
|
||||
// Single solenoid that is reused for forward port
|
||||
Solenoid solenoid{5, frc::PneumaticsModuleType::CTREPCM, 2};
|
||||
Solenoid solenoid{0, 5, frc::PneumaticsModuleType::CTREPCM, 2};
|
||||
EXPECT_THROW(DoubleSolenoid(5, frc::PneumaticsModuleType::CTREPCM, 2, 3),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(DoubleSolenoidREVTest, ThrowReversePortAlreadyInitialized) {
|
||||
// Single solenoid that is reused for forward port
|
||||
Solenoid solenoid{6, frc::PneumaticsModuleType::CTREPCM, 3};
|
||||
Solenoid solenoid{0, 6, frc::PneumaticsModuleType::CTREPCM, 3};
|
||||
EXPECT_THROW(DoubleSolenoid(6, frc::PneumaticsModuleType::CTREPCM, 2, 3),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(DoubleSolenoidREVTest, ThrowBothPortsAlreadyInitialized) {
|
||||
PneumaticsControlModule pcm{6};
|
||||
PneumaticsControlModule pcm{0, 6};
|
||||
// Single solenoid that is reused for forward port
|
||||
Solenoid solenoid0(6, frc::PneumaticsModuleType::CTREPCM, 2);
|
||||
Solenoid solenoid1(6, frc::PneumaticsModuleType::CTREPCM, 3);
|
||||
Solenoid solenoid0(0, 6, frc::PneumaticsModuleType::CTREPCM, 2);
|
||||
Solenoid solenoid1(0, 6, frc::PneumaticsModuleType::CTREPCM, 3);
|
||||
EXPECT_THROW(DoubleSolenoid(6, frc::PneumaticsModuleType::CTREPCM, 2, 3),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(DoubleSolenoidREVTest, Toggle) {
|
||||
DoubleSolenoid solenoid{4, frc::PneumaticsModuleType::CTREPCM, 2, 3};
|
||||
DoubleSolenoid solenoid{0, 4, frc::PneumaticsModuleType::CTREPCM, 2, 3};
|
||||
// Bootstrap it into reverse
|
||||
solenoid.Set(DoubleSolenoid::kReverse);
|
||||
|
||||
@@ -64,12 +64,12 @@ TEST(DoubleSolenoidREVTest, Toggle) {
|
||||
}
|
||||
|
||||
TEST(DoubleSolenoidREVTest, InvalidForwardPort) {
|
||||
EXPECT_THROW(DoubleSolenoid(0, frc::PneumaticsModuleType::CTREPCM, 100, 1),
|
||||
EXPECT_THROW(DoubleSolenoid(0, 0, frc::PneumaticsModuleType::CTREPCM, 100, 1),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(DoubleSolenoidREVTest, InvalidReversePort) {
|
||||
EXPECT_THROW(DoubleSolenoid(0, frc::PneumaticsModuleType::CTREPCM, 0, 100),
|
||||
EXPECT_THROW(DoubleSolenoid(0, 0, frc::PneumaticsModuleType::CTREPCM, 0, 100),
|
||||
std::runtime_error);
|
||||
}
|
||||
} // namespace frc
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
namespace frc {
|
||||
TEST(SolenoidCTRETest, ValidInitialization) {
|
||||
Solenoid solenoid{3, frc::PneumaticsModuleType::CTREPCM, 2};
|
||||
Solenoid solenoid{0, 3, frc::PneumaticsModuleType::CTREPCM, 2};
|
||||
EXPECT_EQ(2, solenoid.GetChannel());
|
||||
|
||||
solenoid.Set(true);
|
||||
@@ -22,24 +22,24 @@ TEST(SolenoidCTRETest, ValidInitialization) {
|
||||
}
|
||||
|
||||
TEST(SolenoidCTRETest, DoubleInitialization) {
|
||||
Solenoid solenoid{3, frc::PneumaticsModuleType::CTREPCM, 2};
|
||||
EXPECT_THROW(Solenoid(3, frc::PneumaticsModuleType::CTREPCM, 2),
|
||||
Solenoid solenoid{0, 3, frc::PneumaticsModuleType::CTREPCM, 2};
|
||||
EXPECT_THROW(Solenoid(0, 3, frc::PneumaticsModuleType::CTREPCM, 2),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(SolenoidCTRETest, DoubleInitializationFromDoubleSolenoid) {
|
||||
DoubleSolenoid solenoid{3, frc::PneumaticsModuleType::CTREPCM, 2, 3};
|
||||
EXPECT_THROW(Solenoid(3, frc::PneumaticsModuleType::CTREPCM, 2),
|
||||
DoubleSolenoid solenoid{0, 3, frc::PneumaticsModuleType::CTREPCM, 2, 3};
|
||||
EXPECT_THROW(Solenoid(0, 3, frc::PneumaticsModuleType::CTREPCM, 2),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(SolenoidCTRETest, InvalidChannel) {
|
||||
EXPECT_THROW(Solenoid(3, frc::PneumaticsModuleType::CTREPCM, 100),
|
||||
EXPECT_THROW(Solenoid(0, 3, frc::PneumaticsModuleType::CTREPCM, 100),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(SolenoidCTRETest, Toggle) {
|
||||
Solenoid solenoid{3, frc::PneumaticsModuleType::CTREPCM, 2};
|
||||
Solenoid solenoid{0, 3, frc::PneumaticsModuleType::CTREPCM, 2};
|
||||
solenoid.Set(true);
|
||||
EXPECT_TRUE(solenoid.Get());
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
namespace frc {
|
||||
TEST(SolenoidREVTest, ValidInitialization) {
|
||||
Solenoid solenoid{3, frc::PneumaticsModuleType::REVPH, 2};
|
||||
Solenoid solenoid{0, 3, frc::PneumaticsModuleType::REVPH, 2};
|
||||
EXPECT_EQ(2, solenoid.GetChannel());
|
||||
|
||||
solenoid.Set(true);
|
||||
@@ -22,24 +22,24 @@ TEST(SolenoidREVTest, ValidInitialization) {
|
||||
}
|
||||
|
||||
TEST(SolenoidREVTest, DoubleInitialization) {
|
||||
Solenoid solenoid{3, frc::PneumaticsModuleType::REVPH, 2};
|
||||
EXPECT_THROW(Solenoid(3, frc::PneumaticsModuleType::REVPH, 2),
|
||||
Solenoid solenoid{0, 3, frc::PneumaticsModuleType::REVPH, 2};
|
||||
EXPECT_THROW(Solenoid(0, 3, frc::PneumaticsModuleType::REVPH, 2),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(SolenoidREVTest, DoubleInitializationFromDoubleSolenoid) {
|
||||
DoubleSolenoid solenoid{3, frc::PneumaticsModuleType::REVPH, 2, 3};
|
||||
EXPECT_THROW(Solenoid(3, frc::PneumaticsModuleType::REVPH, 2),
|
||||
DoubleSolenoid solenoid{0, 3, frc::PneumaticsModuleType::REVPH, 2, 3};
|
||||
EXPECT_THROW(Solenoid(0, 3, frc::PneumaticsModuleType::REVPH, 2),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(SolenoidREVTest, InvalidChannel) {
|
||||
EXPECT_THROW(Solenoid(3, frc::PneumaticsModuleType::REVPH, 100),
|
||||
EXPECT_THROW(Solenoid(0, 3, frc::PneumaticsModuleType::REVPH, 100),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(SolenoidREVTest, Toggle) {
|
||||
Solenoid solenoid{3, frc::PneumaticsModuleType::REVPH, 2};
|
||||
Solenoid solenoid{0, 3, frc::PneumaticsModuleType::REVPH, 2};
|
||||
solenoid.Set(true);
|
||||
EXPECT_TRUE(solenoid.Get());
|
||||
|
||||
|
||||
@@ -22,14 +22,14 @@ TEST(CTREPCMSimTest, InitializedCallback) {
|
||||
BooleanCallback callback;
|
||||
auto cb = sim.RegisterInitializedCallback(callback.GetCallback(), false);
|
||||
|
||||
PneumaticsControlModule pcm;
|
||||
PneumaticsControlModule pcm{0};
|
||||
EXPECT_TRUE(sim.GetInitialized());
|
||||
EXPECT_TRUE(callback.WasTriggered());
|
||||
EXPECT_TRUE(callback.GetLastValue());
|
||||
}
|
||||
|
||||
TEST(CTREPCMSimTest, SolenoidOutput) {
|
||||
PneumaticsControlModule pcm;
|
||||
PneumaticsControlModule pcm{0};
|
||||
CTREPCMSim sim(pcm);
|
||||
sim.ResetData();
|
||||
|
||||
@@ -80,7 +80,7 @@ TEST(CTREPCMSimTest, SolenoidOutput) {
|
||||
}
|
||||
|
||||
TEST(CTREPCMSimTest, SetCompressorOn) {
|
||||
PneumaticsControlModule pcm;
|
||||
PneumaticsControlModule pcm{0};
|
||||
CTREPCMSim sim(pcm);
|
||||
sim.ResetData();
|
||||
|
||||
@@ -97,7 +97,7 @@ TEST(CTREPCMSimTest, SetCompressorOn) {
|
||||
}
|
||||
|
||||
TEST(CTREPCMSimTest, SetEnableDigital) {
|
||||
PneumaticsControlModule pcm;
|
||||
PneumaticsControlModule pcm{0};
|
||||
CTREPCMSim sim(pcm);
|
||||
sim.ResetData();
|
||||
|
||||
@@ -116,7 +116,7 @@ TEST(CTREPCMSimTest, SetEnableDigital) {
|
||||
}
|
||||
|
||||
TEST(CTREPCMSimTest, SetPressureSwitchEnabled) {
|
||||
PneumaticsControlModule pcm;
|
||||
PneumaticsControlModule pcm{0};
|
||||
CTREPCMSim sim(pcm);
|
||||
sim.ResetData();
|
||||
|
||||
@@ -133,7 +133,7 @@ TEST(CTREPCMSimTest, SetPressureSwitchEnabled) {
|
||||
}
|
||||
|
||||
TEST(CTREPCMSimTest, SetCompressorCurrent) {
|
||||
PneumaticsControlModule pcm;
|
||||
PneumaticsControlModule pcm{0};
|
||||
CTREPCMSim sim(pcm);
|
||||
sim.ResetData();
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ TEST(PowerDistributionSimTest, Initialize) {
|
||||
BooleanCallback callback;
|
||||
|
||||
auto cb = sim.RegisterInitializedCallback(callback.GetCallback(), false);
|
||||
PowerDistribution pdp(2, frc::PowerDistribution::ModuleType::kCTRE);
|
||||
PowerDistribution pdp(0, 2, frc::PowerDistribution::ModuleType::kCTRE);
|
||||
EXPECT_TRUE(sim.GetInitialized());
|
||||
EXPECT_TRUE(callback.WasTriggered());
|
||||
EXPECT_TRUE(callback.GetLastValue());
|
||||
@@ -35,7 +35,7 @@ TEST(PowerDistributionSimTest, Initialize) {
|
||||
|
||||
TEST(PowerDistributionSimTest, SetTemperature) {
|
||||
HAL_Initialize(500, 0);
|
||||
PowerDistribution pdp{2, frc::PowerDistribution::ModuleType::kCTRE};
|
||||
PowerDistribution pdp{0, 2, frc::PowerDistribution::ModuleType::kCTRE};
|
||||
PowerDistributionSim sim(pdp);
|
||||
|
||||
DoubleCallback callback;
|
||||
@@ -50,7 +50,7 @@ TEST(PowerDistributionSimTest, SetTemperature) {
|
||||
|
||||
TEST(PowerDistributionSimTest, SetVoltage) {
|
||||
HAL_Initialize(500, 0);
|
||||
PowerDistribution pdp{2, frc::PowerDistribution::ModuleType::kCTRE};
|
||||
PowerDistribution pdp{0, 2, frc::PowerDistribution::ModuleType::kCTRE};
|
||||
PowerDistributionSim sim(pdp);
|
||||
|
||||
DoubleCallback callback;
|
||||
@@ -65,7 +65,7 @@ TEST(PowerDistributionSimTest, SetVoltage) {
|
||||
|
||||
TEST(PowerDistributionSimTest, SetCurrent) {
|
||||
HAL_Initialize(500, 0);
|
||||
PowerDistribution pdp{2, frc::PowerDistribution::ModuleType::kCTRE};
|
||||
PowerDistribution pdp{0, 2, frc::PowerDistribution::ModuleType::kCTRE};
|
||||
PowerDistributionSim sim(pdp);
|
||||
|
||||
for (int channel = 0; channel < HAL_GetNumCTREPDPChannels(); ++channel) {
|
||||
@@ -84,7 +84,7 @@ TEST(PowerDistributionSimTest, SetCurrent) {
|
||||
|
||||
TEST(PowerDistributionSimTest, GetAllCurrents) {
|
||||
HAL_Initialize(500, 0);
|
||||
PowerDistribution pdp{2, frc::PowerDistribution::ModuleType::kRev};
|
||||
PowerDistribution pdp{0, 2, frc::PowerDistribution::ModuleType::kRev};
|
||||
PowerDistributionSim sim(pdp);
|
||||
|
||||
// setup
|
||||
|
||||
@@ -22,18 +22,18 @@ TEST(REVPHSimTest, InitializedCallback) {
|
||||
BooleanCallback callback;
|
||||
auto cb = sim.RegisterInitializedCallback(callback.GetCallback(), false);
|
||||
|
||||
PneumaticHub ph;
|
||||
PneumaticHub ph{0};
|
||||
EXPECT_TRUE(sim.GetInitialized());
|
||||
EXPECT_TRUE(callback.WasTriggered());
|
||||
EXPECT_TRUE(callback.GetLastValue());
|
||||
}
|
||||
|
||||
TEST(REVPHSimTest, SolenoidOutput) {
|
||||
PneumaticHub ph;
|
||||
PneumaticHub ph{0};
|
||||
REVPHSim sim(ph);
|
||||
sim.ResetData();
|
||||
|
||||
DoubleSolenoid doubleSolenoid{1, frc::PneumaticsModuleType::REVPH, 3, 4};
|
||||
DoubleSolenoid doubleSolenoid{0, 1, frc::PneumaticsModuleType::REVPH, 3, 4};
|
||||
|
||||
BooleanCallback callback3;
|
||||
BooleanCallback callback4;
|
||||
@@ -80,7 +80,7 @@ TEST(REVPHSimTest, SolenoidOutput) {
|
||||
}
|
||||
|
||||
TEST(REVPHSimTest, SetCompressorOn) {
|
||||
PneumaticHub ph;
|
||||
PneumaticHub ph{0};
|
||||
REVPHSim sim(ph);
|
||||
sim.ResetData();
|
||||
|
||||
@@ -97,7 +97,7 @@ TEST(REVPHSimTest, SetCompressorOn) {
|
||||
}
|
||||
|
||||
TEST(REVPHSimTest, SetEnableDigital) {
|
||||
PneumaticHub ph;
|
||||
PneumaticHub ph{0};
|
||||
REVPHSim sim(ph);
|
||||
sim.ResetData();
|
||||
|
||||
@@ -118,7 +118,7 @@ TEST(REVPHSimTest, SetEnableDigital) {
|
||||
}
|
||||
|
||||
TEST(REVPHSimTest, SetEnableAnalog) {
|
||||
PneumaticHub ph;
|
||||
PneumaticHub ph{0};
|
||||
REVPHSim sim(ph);
|
||||
sim.ResetData();
|
||||
|
||||
@@ -139,7 +139,7 @@ TEST(REVPHSimTest, SetEnableAnalog) {
|
||||
}
|
||||
|
||||
TEST(REVPHSimTest, SetEnableHybrid) {
|
||||
PneumaticHub ph;
|
||||
PneumaticHub ph{0};
|
||||
REVPHSim sim(ph);
|
||||
sim.ResetData();
|
||||
|
||||
@@ -160,7 +160,7 @@ TEST(REVPHSimTest, SetEnableHybrid) {
|
||||
}
|
||||
|
||||
TEST(REVPHSimTest, SetPressureSwitchEnabled) {
|
||||
PneumaticHub ph;
|
||||
PneumaticHub ph{0};
|
||||
REVPHSim sim(ph);
|
||||
sim.ResetData();
|
||||
|
||||
@@ -177,7 +177,7 @@ TEST(REVPHSimTest, SetPressureSwitchEnabled) {
|
||||
}
|
||||
|
||||
TEST(REVPHSimTest, SetCompressorCurrent) {
|
||||
PneumaticHub ph;
|
||||
PneumaticHub ph{0};
|
||||
REVPHSim sim(ph);
|
||||
sim.ResetData();
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ class Robot : public frc::TimedRobot {
|
||||
|
||||
private:
|
||||
// Object for dealing with the Power Distribution Panel (PDP).
|
||||
frc::PowerDistribution m_pdp;
|
||||
frc::PowerDistribution m_pdp{0};
|
||||
};
|
||||
|
||||
#ifndef RUNNING_FRC_TESTS
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
using namespace HatchConstants;
|
||||
|
||||
HatchSubsystem::HatchSubsystem()
|
||||
: m_hatchSolenoid{frc::PneumaticsModuleType::CTREPCM,
|
||||
: m_hatchSolenoid{0, frc::PneumaticsModuleType::CTREPCM,
|
||||
kHatchSolenoidPorts[0], kHatchSolenoidPorts[1]} {}
|
||||
|
||||
frc2::CommandPtr HatchSubsystem::GrabHatchCommand() {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
using namespace HatchConstants;
|
||||
|
||||
HatchSubsystem::HatchSubsystem()
|
||||
: m_hatchSolenoid{frc::PneumaticsModuleType::CTREPCM,
|
||||
: m_hatchSolenoid{0, frc::PneumaticsModuleType::CTREPCM,
|
||||
kHatchSolenoidPorts[0], kHatchSolenoidPorts[1]} {}
|
||||
|
||||
void HatchSubsystem::GrabHatch() {
|
||||
|
||||
@@ -30,7 +30,7 @@ class Intake : public frc2::SubsystemBase {
|
||||
frc::PWMSparkMax m_motor{IntakeConstants::kMotorPort};
|
||||
|
||||
// Double solenoid connected to two channels of a PCM with the default CAN ID
|
||||
frc::DoubleSolenoid m_piston{frc::PneumaticsModuleType::CTREPCM,
|
||||
frc::DoubleSolenoid m_piston{0, frc::PneumaticsModuleType::CTREPCM,
|
||||
IntakeConstants::kSolenoidPorts[0],
|
||||
IntakeConstants::kSolenoidPorts[1]};
|
||||
};
|
||||
|
||||
@@ -40,5 +40,5 @@ class Pneumatics : frc2::SubsystemBase {
|
||||
kScale, kOffset};
|
||||
|
||||
// Compressor connected to a PH with a default CAN ID
|
||||
frc::Compressor m_compressor{frc::PneumaticsModuleType::CTREPCM};
|
||||
frc::Compressor m_compressor{0, frc::PneumaticsModuleType::CTREPCM};
|
||||
};
|
||||
|
||||
@@ -44,15 +44,16 @@ class Robot : public frc::TimedRobot {
|
||||
// Solenoid corresponds to a single solenoid.
|
||||
// In this case, it's connected to channel 0 of a PH with the default CAN
|
||||
// ID.
|
||||
frc::Solenoid m_solenoid{frc::PneumaticsModuleType::REVPH, 0};
|
||||
frc::Solenoid m_solenoid{0, frc::PneumaticsModuleType::REVPH, 0};
|
||||
|
||||
// DoubleSolenoid corresponds to a double solenoid.
|
||||
// In this case, it's connected to channels 1 and 2 of a PH with the default
|
||||
// CAN ID.
|
||||
frc::DoubleSolenoid m_doubleSolenoid{frc::PneumaticsModuleType::REVPH, 1, 2};
|
||||
frc::DoubleSolenoid m_doubleSolenoid{0, frc::PneumaticsModuleType::REVPH, 1,
|
||||
2};
|
||||
|
||||
// Compressor connected to a PH with a default CAN ID
|
||||
frc::Compressor m_compressor{frc::PneumaticsModuleType::REVPH};
|
||||
frc::Compressor m_compressor{0, frc::PneumaticsModuleType::REVPH};
|
||||
|
||||
static constexpr int kSolenoidButton = 1;
|
||||
static constexpr int kDoubleSolenoidForward = 2;
|
||||
|
||||
@@ -18,7 +18,7 @@ class Intake {
|
||||
|
||||
private:
|
||||
frc::PWMSparkMax m_motor{IntakeConstants::kMotorPort};
|
||||
frc::DoubleSolenoid m_piston{frc::PneumaticsModuleType::CTREPCM,
|
||||
frc::DoubleSolenoid m_piston{0, frc::PneumaticsModuleType::CTREPCM,
|
||||
IntakeConstants::kPistonFwdChannel,
|
||||
IntakeConstants::kPistonRevChannel};
|
||||
};
|
||||
|
||||
@@ -6,8 +6,8 @@ package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.hal.CANAPIJNI;
|
||||
import edu.wpi.first.hal.CANAPITypes;
|
||||
import edu.wpi.first.hal.CANData;
|
||||
import edu.wpi.first.hal.HAL;
|
||||
import edu.wpi.first.hal.can.CANReceiveMessage;
|
||||
import java.io.Closeable;
|
||||
|
||||
/**
|
||||
@@ -33,22 +33,24 @@ public class CAN implements Closeable {
|
||||
* Create a new CAN communication interface with the specific device ID. This uses the team
|
||||
* manufacturer and device types. The device ID is 6 bits (0-63).
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @param deviceId The device id
|
||||
*/
|
||||
public CAN(int deviceId) {
|
||||
this(kTeamManufacturer, deviceId, kTeamDeviceType);
|
||||
public CAN(int busId, int deviceId) {
|
||||
this(busId, deviceId, kTeamManufacturer, kTeamDeviceType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new CAN communication interface with a specific device ID, manufacturer and device
|
||||
* type. The device ID is 6 bits, the manufacturer is 8 bits, and the device type is 5 bits.
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @param deviceId The device ID
|
||||
* @param deviceManufacturer The device manufacturer
|
||||
* @param deviceType The device type
|
||||
*/
|
||||
public CAN(int deviceId, int deviceManufacturer, int deviceType) {
|
||||
m_handle = CANAPIJNI.initializeCAN(deviceManufacturer, deviceId, deviceType);
|
||||
public CAN(int busId, int deviceId, int deviceManufacturer, int deviceType) {
|
||||
m_handle = CANAPIJNI.initializeCAN(busId, deviceManufacturer, deviceId, deviceType);
|
||||
HAL.reportUsage("CAN[" + deviceType + "][" + deviceManufacturer + "][" + deviceId + "]", "");
|
||||
}
|
||||
|
||||
@@ -63,70 +65,85 @@ public class CAN implements Closeable {
|
||||
/**
|
||||
* Write a packet to the CAN device with a specific ID. This ID is 10 bits.
|
||||
*
|
||||
* @param data The data to write (8 bytes max)
|
||||
* @param apiId The API ID to write.
|
||||
* @param data The data to write
|
||||
* @param dataLength The data length
|
||||
* @param flags The flags
|
||||
*/
|
||||
public void writePacket(byte[] data, int apiId) {
|
||||
CANAPIJNI.writeCANPacket(m_handle, data, apiId);
|
||||
public void writePacket(int apiId, byte[] data, int dataLength, int flags) {
|
||||
CANAPIJNI.writeCANPacket(m_handle, apiId, data, dataLength, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 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
|
||||
*
|
||||
* @param data The data to write (8 bytes max)
|
||||
* @param apiId The API ID to write.
|
||||
* @param data The data to write
|
||||
* @param dataLength The data length
|
||||
* @param flags The flags
|
||||
* @param repeatMs The period to repeat the packet at.
|
||||
*/
|
||||
public void writePacketRepeating(byte[] data, int apiId, int repeatMs) {
|
||||
CANAPIJNI.writeCANPacketRepeating(m_handle, data, apiId, repeatMs);
|
||||
public void writePacketRepeating(
|
||||
int apiId, byte[] data, int dataLength, int flags, int repeatMs) {
|
||||
CANAPIJNI.writeCANPacketRepeating(m_handle, apiId, data, dataLength, flags, repeatMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an RTR frame to the CAN device with a specific ID. This ID is 10 bits. The length by spec
|
||||
* must match what is returned by the responding device
|
||||
*
|
||||
* @param length The length to request (0 to 8)
|
||||
* @param apiId The API ID to write.
|
||||
* @param data The data to write
|
||||
* @param dataLength The data length
|
||||
* @param flags The flags
|
||||
*/
|
||||
public void writeRTRFrame(int length, int apiId) {
|
||||
CANAPIJNI.writeCANRTRFrame(m_handle, length, apiId);
|
||||
public void writeRTRFrame(int apiId, byte[] data, int dataLength, int flags) {
|
||||
CANAPIJNI.writeCANRTRFrame(m_handle, apiId, data, dataLength, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a packet to the CAN device with a specific ID. This ID is 10 bits.
|
||||
*
|
||||
* @param data The data to write (8 bytes max)
|
||||
* @param apiId The API ID to write.
|
||||
* @param data The data to write
|
||||
* @param dataLength The data length
|
||||
* @param flags The flags
|
||||
* @return TODO
|
||||
*/
|
||||
public int writePacketNoThrow(byte[] data, int apiId) {
|
||||
return CANAPIJNI.writeCANPacketNoThrow(m_handle, data, apiId);
|
||||
public int writePacketNoThrow(int apiId, byte[] data, int dataLength, int flags) {
|
||||
return CANAPIJNI.writeCANPacketNoThrow(m_handle, apiId, data, dataLength, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 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
|
||||
*
|
||||
* @param data The data to write (8 bytes max)
|
||||
* @param apiId The API ID to write.
|
||||
* @param data The data to write
|
||||
* @param dataLength The data length
|
||||
* @param flags The flags
|
||||
* @param repeatMs The period to repeat the packet at.
|
||||
* @return TODO
|
||||
*/
|
||||
public int writePacketRepeatingNoThrow(byte[] data, int apiId, int repeatMs) {
|
||||
return CANAPIJNI.writeCANPacketRepeatingNoThrow(m_handle, data, apiId, repeatMs);
|
||||
public int writePacketRepeatingNoThrow(
|
||||
int apiId, byte[] data, int dataLength, int flags, int repeatMs) {
|
||||
return CANAPIJNI.writeCANPacketRepeatingNoThrow(
|
||||
m_handle, apiId, data, dataLength, flags, repeatMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an RTR frame to the CAN device with a specific ID. This ID is 10 bits. The length by spec
|
||||
* must match what is returned by the responding device
|
||||
*
|
||||
* @param length The length to request (0 to 8)
|
||||
* @param apiId The API ID to write.
|
||||
* @param data The data to write
|
||||
* @param dataLength The data length
|
||||
* @param flags The flags
|
||||
* @return TODO
|
||||
*/
|
||||
public int writeRTRFrameNoThrow(int length, int apiId) {
|
||||
return CANAPIJNI.writeCANRTRFrameNoThrow(m_handle, length, apiId);
|
||||
public int writeRTRFrameNoThrow(int apiId, byte[] data, int dataLength, int flags) {
|
||||
return CANAPIJNI.writeCANRTRFrameNoThrow(m_handle, apiId, data, dataLength, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +163,7 @@ public class CAN implements Closeable {
|
||||
* @param data Storage for the received data.
|
||||
* @return True if the data is valid, otherwise false.
|
||||
*/
|
||||
public boolean readPacketNew(int apiId, CANData data) {
|
||||
public boolean readPacketNew(int apiId, CANReceiveMessage data) {
|
||||
return CANAPIJNI.readCANPacketNew(m_handle, apiId, data);
|
||||
}
|
||||
|
||||
@@ -158,7 +175,7 @@ public class CAN implements Closeable {
|
||||
* @param data Storage for the received data.
|
||||
* @return True if the data is valid, otherwise false.
|
||||
*/
|
||||
public boolean readPacketLatest(int apiId, CANData data) {
|
||||
public boolean readPacketLatest(int apiId, CANReceiveMessage data) {
|
||||
return CANAPIJNI.readCANPacketLatest(m_handle, apiId, data);
|
||||
}
|
||||
|
||||
@@ -171,18 +188,7 @@ public class CAN implements Closeable {
|
||||
* @param data Storage for the received data.
|
||||
* @return True if the data is valid, otherwise false.
|
||||
*/
|
||||
public boolean readPacketTimeout(int apiId, int timeoutMs, CANData data) {
|
||||
return CANAPIJNI.readCANPacketTimeout(m_handle, apiId, timeoutMs, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the current value of the millisecond-resolution timer that {@link CANData} timestamps are
|
||||
* based on.
|
||||
*
|
||||
* @return Current value of timer used as a base time for {@link CANData} timestamps in
|
||||
* milliseconds
|
||||
*/
|
||||
public static long getTimestampBaseTime() {
|
||||
return CANAPIJNI.getCANPacketBaseTime();
|
||||
public boolean readPacketTimeout(int apiId, CANReceiveMessage data, int timeoutMs) {
|
||||
return CANAPIJNI.readCANPacketTimeout(m_handle, apiId, data, timeoutMs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,12 +27,13 @@ public class Compressor implements Sendable, AutoCloseable {
|
||||
/**
|
||||
* Constructs a compressor for a specified module and type.
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @param module The module ID to use.
|
||||
* @param moduleType The module type to use.
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public Compressor(int module, PneumaticsModuleType moduleType) {
|
||||
m_module = PneumaticsBase.getForType(module, moduleType);
|
||||
public Compressor(int busId, int module, PneumaticsModuleType moduleType) {
|
||||
m_module = PneumaticsBase.getForType(busId, module, moduleType);
|
||||
m_moduleType = moduleType;
|
||||
|
||||
if (!m_module.reserveCompressor()) {
|
||||
@@ -49,10 +50,11 @@ public class Compressor implements Sendable, AutoCloseable {
|
||||
/**
|
||||
* Constructs a compressor for a default module and specified type.
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @param moduleType The module type to use.
|
||||
*/
|
||||
public Compressor(PneumaticsModuleType moduleType) {
|
||||
this(PneumaticsBase.getDefaultForType(moduleType), moduleType);
|
||||
public Compressor(int busId, PneumaticsModuleType moduleType) {
|
||||
this(busId, PneumaticsBase.getDefaultForType(moduleType), moduleType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,18 +37,28 @@ public class DoubleSolenoid implements Sendable, AutoCloseable {
|
||||
/**
|
||||
* Constructs a double solenoid for a default module of a specific module type.
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @param moduleType The module type to use.
|
||||
* @param forwardChannel The forward channel on the module to control.
|
||||
* @param reverseChannel The reverse channel on the module to control.
|
||||
*/
|
||||
public DoubleSolenoid(
|
||||
final PneumaticsModuleType moduleType, final int forwardChannel, final int reverseChannel) {
|
||||
this(PneumaticsBase.getDefaultForType(moduleType), moduleType, forwardChannel, reverseChannel);
|
||||
final int busId,
|
||||
final PneumaticsModuleType moduleType,
|
||||
final int forwardChannel,
|
||||
final int reverseChannel) {
|
||||
this(
|
||||
busId,
|
||||
PneumaticsBase.getDefaultForType(moduleType),
|
||||
moduleType,
|
||||
forwardChannel,
|
||||
reverseChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a double solenoid for a specified module of a specific module type.
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @param module The module of the solenoid module to use.
|
||||
* @param moduleType The module type to use.
|
||||
* @param forwardChannel The forward channel on the module to control.
|
||||
@@ -56,11 +66,12 @@ public class DoubleSolenoid implements Sendable, AutoCloseable {
|
||||
*/
|
||||
@SuppressWarnings({"PMD.UseTryWithResources", "this-escape"})
|
||||
public DoubleSolenoid(
|
||||
final int busId,
|
||||
final int module,
|
||||
final PneumaticsModuleType moduleType,
|
||||
final int forwardChannel,
|
||||
final int reverseChannel) {
|
||||
m_module = PneumaticsBase.getForType(module, moduleType);
|
||||
m_module = PneumaticsBase.getForType(busId, module, moduleType);
|
||||
boolean allocatedSolenoids = false;
|
||||
boolean successfulCompletion = false;
|
||||
|
||||
|
||||
@@ -23,16 +23,18 @@ public class PneumaticHub implements PneumaticsBase {
|
||||
private static class DataStore implements AutoCloseable {
|
||||
public final int m_module;
|
||||
public final int m_handle;
|
||||
private final int m_busId;
|
||||
private int m_refCount;
|
||||
private int m_reservedMask;
|
||||
private boolean m_compressorReserved;
|
||||
public final int[] m_oneShotDurMs = new int[PortsJNI.getNumREVPHChannels()];
|
||||
private final Object m_reserveLock = new Object();
|
||||
|
||||
DataStore(int module) {
|
||||
m_handle = REVPHJNI.initialize(module);
|
||||
DataStore(int busId, int module) {
|
||||
m_handle = REVPHJNI.initialize(busId, module);
|
||||
m_module = module;
|
||||
m_handleMap.put(module, this);
|
||||
m_busId = busId;
|
||||
m_handleMaps[busId].put(module, this);
|
||||
|
||||
final REVPHVersion version = REVPHJNI.getVersion(m_handle);
|
||||
final String fwVersion =
|
||||
@@ -77,7 +79,7 @@ public class PneumaticHub implements PneumaticsBase {
|
||||
@Override
|
||||
public void close() {
|
||||
REVPHJNI.free(m_handle);
|
||||
m_handleMap.remove(m_module);
|
||||
m_handleMaps[m_busId].remove(m_module);
|
||||
}
|
||||
|
||||
public void addRef() {
|
||||
@@ -92,14 +94,23 @@ public class PneumaticHub implements PneumaticsBase {
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<Integer, DataStore> m_handleMap = new HashMap<>();
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private static final Map<Integer, DataStore>[] m_handleMaps =
|
||||
(Map<Integer, DataStore>[]) new Map[PortsJNI.getNumCanBuses()];
|
||||
|
||||
private static final Object m_handleLock = new Object();
|
||||
|
||||
private static DataStore getForModule(int module) {
|
||||
private static DataStore getForModule(int busId, int module) {
|
||||
synchronized (m_handleLock) {
|
||||
DataStore pcm = m_handleMap.get(module);
|
||||
Map<Integer, DataStore> handleMap = m_handleMaps[busId];
|
||||
if (handleMap == null) {
|
||||
handleMap = new HashMap<>();
|
||||
m_handleMaps[busId] = handleMap;
|
||||
}
|
||||
|
||||
DataStore pcm = handleMap.get(module);
|
||||
if (pcm == null) {
|
||||
pcm = new DataStore(module);
|
||||
pcm = new DataStore(busId, module);
|
||||
}
|
||||
pcm.addRef();
|
||||
return pcm;
|
||||
@@ -125,18 +136,23 @@ public class PneumaticHub implements PneumaticsBase {
|
||||
private final DataStore m_dataStore;
|
||||
private final int m_handle;
|
||||
|
||||
/** Constructs a PneumaticHub with the default ID (1). */
|
||||
public PneumaticHub() {
|
||||
this(SensorUtil.getDefaultREVPHModule());
|
||||
/**
|
||||
* Constructs a PneumaticHub with the default ID (1).
|
||||
*
|
||||
* @param busId The bus ID
|
||||
*/
|
||||
public PneumaticHub(int busId) {
|
||||
this(busId, SensorUtil.getDefaultREVPHModule());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PneumaticHub.
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @param module module number to construct
|
||||
*/
|
||||
public PneumaticHub(int module) {
|
||||
m_dataStore = getForModule(module);
|
||||
public PneumaticHub(int busId, int module) {
|
||||
m_dataStore = getForModule(busId, module);
|
||||
m_handle = m_dataStore.m_handle;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,14 +9,15 @@ public interface PneumaticsBase extends AutoCloseable {
|
||||
/**
|
||||
* For internal use to get a module for a specific type.
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @param module module number
|
||||
* @param type module type
|
||||
* @return module
|
||||
*/
|
||||
static PneumaticsBase getForType(int module, PneumaticsModuleType type) {
|
||||
static PneumaticsBase getForType(int busId, int module, PneumaticsModuleType type) {
|
||||
return switch (type) {
|
||||
case CTREPCM -> new PneumaticsControlModule(module);
|
||||
case REVPH -> new PneumaticHub(module);
|
||||
case CTREPCM -> new PneumaticsControlModule(busId, module);
|
||||
case REVPH -> new PneumaticHub(busId, module);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.hal.CTREPCMJNI;
|
||||
import edu.wpi.first.hal.HAL;
|
||||
import edu.wpi.first.hal.PortsJNI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -14,21 +15,23 @@ public class PneumaticsControlModule implements PneumaticsBase {
|
||||
private static class DataStore implements AutoCloseable {
|
||||
public final int m_module;
|
||||
public final int m_handle;
|
||||
private final int m_busId;
|
||||
private int m_refCount;
|
||||
private int m_reservedMask;
|
||||
private boolean m_compressorReserved;
|
||||
private final Object m_reserveLock = new Object();
|
||||
|
||||
DataStore(int module) {
|
||||
m_handle = CTREPCMJNI.initialize(module);
|
||||
DataStore(int busId, int module) {
|
||||
m_handle = CTREPCMJNI.initialize(busId, module);
|
||||
m_module = module;
|
||||
m_handleMap.put(module, this);
|
||||
m_busId = busId;
|
||||
m_handleMaps[busId].put(module, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
CTREPCMJNI.free(m_handle);
|
||||
m_handleMap.remove(m_module);
|
||||
m_handleMaps[m_busId].remove(m_module);
|
||||
}
|
||||
|
||||
public void addRef() {
|
||||
@@ -43,14 +46,23 @@ public class PneumaticsControlModule implements PneumaticsBase {
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<Integer, DataStore> m_handleMap = new HashMap<>();
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private static final Map<Integer, DataStore>[] m_handleMaps =
|
||||
(Map<Integer, DataStore>[]) new Map[PortsJNI.getNumCanBuses()];
|
||||
|
||||
private static final Object m_handleLock = new Object();
|
||||
|
||||
private static DataStore getForModule(int module) {
|
||||
private static DataStore getForModule(int busId, int module) {
|
||||
synchronized (m_handleLock) {
|
||||
DataStore pcm = m_handleMap.get(module);
|
||||
Map<Integer, DataStore> handleMap = m_handleMaps[busId];
|
||||
if (handleMap == null) {
|
||||
handleMap = new HashMap<>();
|
||||
m_handleMaps[busId] = handleMap;
|
||||
}
|
||||
|
||||
DataStore pcm = handleMap.get(module);
|
||||
if (pcm == null) {
|
||||
pcm = new DataStore(module);
|
||||
pcm = new DataStore(busId, module);
|
||||
}
|
||||
pcm.addRef();
|
||||
return pcm;
|
||||
@@ -66,18 +78,23 @@ public class PneumaticsControlModule implements PneumaticsBase {
|
||||
private final DataStore m_dataStore;
|
||||
private final int m_handle;
|
||||
|
||||
/** Constructs a PneumaticsControlModule with the default ID (0). */
|
||||
public PneumaticsControlModule() {
|
||||
this(SensorUtil.getDefaultCTREPCMModule());
|
||||
/**
|
||||
* Constructs a PneumaticsControlModule with the default ID (0).
|
||||
*
|
||||
* @param busId The bus ID
|
||||
*/
|
||||
public PneumaticsControlModule(int busId) {
|
||||
this(busId, SensorUtil.getDefaultCTREPCMModule());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PneumaticsControlModule.
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @param module module number to construct
|
||||
*/
|
||||
public PneumaticsControlModule(int module) {
|
||||
m_dataStore = getForModule(module);
|
||||
public PneumaticsControlModule(int busId, int module) {
|
||||
m_dataStore = getForModule(busId, module);
|
||||
m_handle = m_dataStore.m_handle;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,12 +42,13 @@ public class PowerDistribution implements Sendable, AutoCloseable {
|
||||
/**
|
||||
* Constructs a PowerDistribution object.
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @param module The CAN ID of the PDP/PDH.
|
||||
* @param moduleType Module type (CTRE or REV).
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public PowerDistribution(int module, ModuleType moduleType) {
|
||||
m_handle = PowerDistributionJNI.initialize(module, moduleType.value);
|
||||
public PowerDistribution(int busId, int module, ModuleType moduleType) {
|
||||
m_handle = PowerDistributionJNI.initialize(busId, module, moduleType.value);
|
||||
m_module = PowerDistributionJNI.getModuleNumber(m_handle);
|
||||
|
||||
if (moduleType == ModuleType.kCTRE) {
|
||||
@@ -62,10 +63,13 @@ public class PowerDistribution implements Sendable, AutoCloseable {
|
||||
* Constructs a PowerDistribution object.
|
||||
*
|
||||
* <p>Detects the connected PDP/PDH using the default CAN ID (0 for CTRE and 1 for REV).
|
||||
*
|
||||
* @param busId The bus ID
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public PowerDistribution() {
|
||||
m_handle = PowerDistributionJNI.initialize(kDefaultModule, PowerDistributionJNI.AUTOMATIC_TYPE);
|
||||
public PowerDistribution(int busId) {
|
||||
m_handle =
|
||||
PowerDistributionJNI.initialize(busId, kDefaultModule, PowerDistributionJNI.AUTOMATIC_TYPE);
|
||||
m_module = PowerDistributionJNI.getModuleNumber(m_handle);
|
||||
|
||||
if (PowerDistributionJNI.getType(m_handle) == PowerDistributionJNI.CTRE_TYPE) {
|
||||
|
||||
@@ -556,11 +556,12 @@ public final class RobotController {
|
||||
/**
|
||||
* Get the current status of the CAN bus.
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @return The status of the CAN bus
|
||||
*/
|
||||
public static CANStatus getCANStatus() {
|
||||
public static CANStatus getCANStatus(int busId) {
|
||||
CANStatus status = new CANStatus();
|
||||
CANJNI.getCANStatus(status);
|
||||
CANJNI.getCANStatus(busId, status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,23 +23,26 @@ public class Solenoid implements Sendable, AutoCloseable {
|
||||
/**
|
||||
* Constructs a solenoid for a default module and specified type.
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @param moduleType The module type to use.
|
||||
* @param channel The channel the solenoid is on.
|
||||
*/
|
||||
public Solenoid(final PneumaticsModuleType moduleType, final int channel) {
|
||||
this(PneumaticsBase.getDefaultForType(moduleType), moduleType, channel);
|
||||
public Solenoid(final int busId, final PneumaticsModuleType moduleType, final int channel) {
|
||||
this(busId, PneumaticsBase.getDefaultForType(moduleType), moduleType, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a solenoid for a specified module and type.
|
||||
*
|
||||
* @param busId The bus ID
|
||||
* @param module The module ID to use.
|
||||
* @param moduleType The module type to use.
|
||||
* @param channel The channel the solenoid is on.
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public Solenoid(final int module, final PneumaticsModuleType moduleType, final int channel) {
|
||||
m_module = PneumaticsBase.getForType(module, moduleType);
|
||||
public Solenoid(
|
||||
final int busId, final int module, final PneumaticsModuleType moduleType, final int channel) {
|
||||
m_module = PneumaticsBase.getForType(busId, module, moduleType);
|
||||
|
||||
m_mask = 1 << channel;
|
||||
m_channel = channel;
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.junit.jupiter.api.Test;
|
||||
class DoubleSolenoidTestCTRE {
|
||||
@Test
|
||||
void testValidInitialization() {
|
||||
try (DoubleSolenoid solenoid = new DoubleSolenoid(3, PneumaticsModuleType.CTREPCM, 2, 3)) {
|
||||
try (DoubleSolenoid solenoid = new DoubleSolenoid(0, 3, PneumaticsModuleType.CTREPCM, 2, 3)) {
|
||||
solenoid.set(DoubleSolenoid.Value.kReverse);
|
||||
assertEquals(DoubleSolenoid.Value.kReverse, solenoid.get());
|
||||
|
||||
@@ -29,10 +29,10 @@ class DoubleSolenoidTestCTRE {
|
||||
void testThrowForwardPortAlreadyInitialized() {
|
||||
try (
|
||||
// Single solenoid that is reused for forward port
|
||||
Solenoid solenoid = new Solenoid(5, PneumaticsModuleType.CTREPCM, 2)) {
|
||||
Solenoid solenoid = new Solenoid(0, 5, PneumaticsModuleType.CTREPCM, 2)) {
|
||||
assertThrows(
|
||||
AllocationException.class,
|
||||
() -> new DoubleSolenoid(5, PneumaticsModuleType.CTREPCM, 2, 3));
|
||||
() -> new DoubleSolenoid(0, 5, PneumaticsModuleType.CTREPCM, 2, 3));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,10 +40,10 @@ class DoubleSolenoidTestCTRE {
|
||||
void testThrowReversePortAlreadyInitialized() {
|
||||
try (
|
||||
// Single solenoid that is reused for forward port
|
||||
Solenoid solenoid = new Solenoid(6, PneumaticsModuleType.CTREPCM, 3)) {
|
||||
Solenoid solenoid = new Solenoid(0, 6, PneumaticsModuleType.CTREPCM, 3)) {
|
||||
assertThrows(
|
||||
AllocationException.class,
|
||||
() -> new DoubleSolenoid(6, PneumaticsModuleType.CTREPCM, 2, 3));
|
||||
() -> new DoubleSolenoid(0, 6, PneumaticsModuleType.CTREPCM, 2, 3));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,17 +51,17 @@ class DoubleSolenoidTestCTRE {
|
||||
void testThrowBothPortsAlreadyInitialized() {
|
||||
try (
|
||||
// Single solenoid that is reused for forward port
|
||||
Solenoid solenoid0 = new Solenoid(6, PneumaticsModuleType.CTREPCM, 2);
|
||||
Solenoid solenoid1 = new Solenoid(6, PneumaticsModuleType.CTREPCM, 3)) {
|
||||
Solenoid solenoid0 = new Solenoid(0, 6, PneumaticsModuleType.CTREPCM, 2);
|
||||
Solenoid solenoid1 = new Solenoid(0, 6, PneumaticsModuleType.CTREPCM, 3)) {
|
||||
assertThrows(
|
||||
AllocationException.class,
|
||||
() -> new DoubleSolenoid(6, PneumaticsModuleType.CTREPCM, 2, 3));
|
||||
() -> new DoubleSolenoid(0, 6, PneumaticsModuleType.CTREPCM, 2, 3));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToggle() {
|
||||
try (DoubleSolenoid solenoid = new DoubleSolenoid(4, PneumaticsModuleType.CTREPCM, 2, 3)) {
|
||||
try (DoubleSolenoid solenoid = new DoubleSolenoid(0, 4, PneumaticsModuleType.CTREPCM, 2, 3)) {
|
||||
// Bootstrap it into reverse
|
||||
solenoid.set(DoubleSolenoid.Value.kReverse);
|
||||
|
||||
@@ -82,13 +82,13 @@ class DoubleSolenoidTestCTRE {
|
||||
void testInvalidForwardPort() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new DoubleSolenoid(0, PneumaticsModuleType.CTREPCM, 100, 1));
|
||||
() -> new DoubleSolenoid(0, 0, PneumaticsModuleType.CTREPCM, 100, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidReversePort() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new DoubleSolenoid(0, PneumaticsModuleType.CTREPCM, 0, 100));
|
||||
() -> new DoubleSolenoid(0, 0, PneumaticsModuleType.CTREPCM, 0, 100));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.junit.jupiter.api.Test;
|
||||
class DoubleSolenoidTestREV {
|
||||
@Test
|
||||
void testValidInitialization() {
|
||||
try (DoubleSolenoid solenoid = new DoubleSolenoid(3, PneumaticsModuleType.REVPH, 2, 3)) {
|
||||
try (DoubleSolenoid solenoid = new DoubleSolenoid(0, 3, PneumaticsModuleType.REVPH, 2, 3)) {
|
||||
solenoid.set(DoubleSolenoid.Value.kReverse);
|
||||
assertEquals(DoubleSolenoid.Value.kReverse, solenoid.get());
|
||||
|
||||
@@ -29,9 +29,10 @@ class DoubleSolenoidTestREV {
|
||||
void testThrowForwardPortAlreadyInitialized() {
|
||||
try (
|
||||
// Single solenoid that is reused for forward port
|
||||
Solenoid solenoid = new Solenoid(5, PneumaticsModuleType.REVPH, 2)) {
|
||||
Solenoid solenoid = new Solenoid(0, 5, PneumaticsModuleType.REVPH, 2)) {
|
||||
assertThrows(
|
||||
AllocationException.class, () -> new DoubleSolenoid(5, PneumaticsModuleType.REVPH, 2, 3));
|
||||
AllocationException.class,
|
||||
() -> new DoubleSolenoid(0, 5, PneumaticsModuleType.REVPH, 2, 3));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,9 +40,10 @@ class DoubleSolenoidTestREV {
|
||||
void testThrowReversePortAlreadyInitialized() {
|
||||
try (
|
||||
// Single solenoid that is reused for forward port
|
||||
Solenoid solenoid = new Solenoid(6, PneumaticsModuleType.REVPH, 3)) {
|
||||
Solenoid solenoid = new Solenoid(0, 6, PneumaticsModuleType.REVPH, 3)) {
|
||||
assertThrows(
|
||||
AllocationException.class, () -> new DoubleSolenoid(6, PneumaticsModuleType.REVPH, 2, 3));
|
||||
AllocationException.class,
|
||||
() -> new DoubleSolenoid(0, 6, PneumaticsModuleType.REVPH, 2, 3));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,16 +51,17 @@ class DoubleSolenoidTestREV {
|
||||
void testThrowBothPortsAlreadyInitialized() {
|
||||
try (
|
||||
// Single solenoid that is reused for forward port
|
||||
Solenoid solenoid0 = new Solenoid(6, PneumaticsModuleType.REVPH, 2);
|
||||
Solenoid solenoid1 = new Solenoid(6, PneumaticsModuleType.REVPH, 3)) {
|
||||
Solenoid solenoid0 = new Solenoid(0, 6, PneumaticsModuleType.REVPH, 2);
|
||||
Solenoid solenoid1 = new Solenoid(0, 6, PneumaticsModuleType.REVPH, 3)) {
|
||||
assertThrows(
|
||||
AllocationException.class, () -> new DoubleSolenoid(6, PneumaticsModuleType.REVPH, 2, 3));
|
||||
AllocationException.class,
|
||||
() -> new DoubleSolenoid(0, 6, PneumaticsModuleType.REVPH, 2, 3));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToggle() {
|
||||
try (DoubleSolenoid solenoid = new DoubleSolenoid(4, PneumaticsModuleType.REVPH, 2, 3)) {
|
||||
try (DoubleSolenoid solenoid = new DoubleSolenoid(0, 4, PneumaticsModuleType.REVPH, 2, 3)) {
|
||||
// Bootstrap it into reverse
|
||||
solenoid.set(DoubleSolenoid.Value.kReverse);
|
||||
|
||||
@@ -79,13 +82,13 @@ class DoubleSolenoidTestREV {
|
||||
void testInvalidForwardPort() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new DoubleSolenoid(1, PneumaticsModuleType.REVPH, 100, 1));
|
||||
() -> new DoubleSolenoid(0, 1, PneumaticsModuleType.REVPH, 100, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidReversePort() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new DoubleSolenoid(1, PneumaticsModuleType.REVPH, 0, 100));
|
||||
() -> new DoubleSolenoid(0, 1, PneumaticsModuleType.REVPH, 0, 100));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ class PowerDistributionTest {
|
||||
@Test
|
||||
void testGetAllCurrents() {
|
||||
HAL.initialize(500, 0);
|
||||
PowerDistribution pdp = new PowerDistribution(1, ModuleType.kRev);
|
||||
PowerDistribution pdp = new PowerDistribution(0, 1, ModuleType.kRev);
|
||||
PDPSim sim = new PDPSim(pdp);
|
||||
|
||||
for (int i = 0; i < pdp.getNumChannels(); i++) {
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.junit.jupiter.api.Test;
|
||||
class SolenoidTestCTRE {
|
||||
@Test
|
||||
void testValidInitialization() {
|
||||
try (Solenoid solenoid = new Solenoid(3, PneumaticsModuleType.CTREPCM, 2)) {
|
||||
try (Solenoid solenoid = new Solenoid(0, 3, PneumaticsModuleType.CTREPCM, 2)) {
|
||||
assertEquals(2, solenoid.getChannel());
|
||||
|
||||
solenoid.set(true);
|
||||
@@ -28,29 +28,30 @@ class SolenoidTestCTRE {
|
||||
|
||||
@Test
|
||||
void testDoubleInitialization() {
|
||||
try (Solenoid solenoid = new Solenoid(3, PneumaticsModuleType.CTREPCM, 2)) {
|
||||
try (Solenoid solenoid = new Solenoid(0, 3, PneumaticsModuleType.CTREPCM, 2)) {
|
||||
assertThrows(
|
||||
AllocationException.class, () -> new Solenoid(3, PneumaticsModuleType.CTREPCM, 2));
|
||||
AllocationException.class, () -> new Solenoid(0, 3, PneumaticsModuleType.CTREPCM, 2));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDoubleInitializationFromDoubleSolenoid() {
|
||||
try (DoubleSolenoid solenoid = new DoubleSolenoid(3, PneumaticsModuleType.CTREPCM, 2, 3)) {
|
||||
try (DoubleSolenoid solenoid = new DoubleSolenoid(0, 3, PneumaticsModuleType.CTREPCM, 2, 3)) {
|
||||
assertThrows(
|
||||
AllocationException.class, () -> new Solenoid(3, PneumaticsModuleType.CTREPCM, 2));
|
||||
AllocationException.class, () -> new Solenoid(0, 3, PneumaticsModuleType.CTREPCM, 2));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidChannel() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class, () -> new Solenoid(3, PneumaticsModuleType.CTREPCM, 100));
|
||||
IllegalArgumentException.class,
|
||||
() -> new Solenoid(0, 3, PneumaticsModuleType.CTREPCM, 100));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToggle() {
|
||||
try (Solenoid solenoid = new Solenoid(3, PneumaticsModuleType.CTREPCM, 2)) {
|
||||
try (Solenoid solenoid = new Solenoid(0, 3, PneumaticsModuleType.CTREPCM, 2)) {
|
||||
solenoid.set(true);
|
||||
assertTrue(solenoid.get());
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.junit.jupiter.api.Test;
|
||||
class SolenoidTestREV {
|
||||
@Test
|
||||
void testValidInitialization() {
|
||||
try (Solenoid solenoid = new Solenoid(3, PneumaticsModuleType.REVPH, 2)) {
|
||||
try (Solenoid solenoid = new Solenoid(0, 3, PneumaticsModuleType.REVPH, 2)) {
|
||||
assertEquals(2, solenoid.getChannel());
|
||||
|
||||
solenoid.set(true);
|
||||
@@ -28,27 +28,29 @@ class SolenoidTestREV {
|
||||
|
||||
@Test
|
||||
void testDoubleInitialization() {
|
||||
try (Solenoid solenoid = new Solenoid(3, PneumaticsModuleType.REVPH, 2)) {
|
||||
assertThrows(AllocationException.class, () -> new Solenoid(3, PneumaticsModuleType.REVPH, 2));
|
||||
try (Solenoid solenoid = new Solenoid(0, 3, PneumaticsModuleType.REVPH, 2)) {
|
||||
assertThrows(
|
||||
AllocationException.class, () -> new Solenoid(0, 3, PneumaticsModuleType.REVPH, 2));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDoubleInitializationFromDoubleSolenoid() {
|
||||
try (DoubleSolenoid solenoid = new DoubleSolenoid(3, PneumaticsModuleType.REVPH, 2, 3)) {
|
||||
assertThrows(AllocationException.class, () -> new Solenoid(3, PneumaticsModuleType.REVPH, 2));
|
||||
try (DoubleSolenoid solenoid = new DoubleSolenoid(0, 3, PneumaticsModuleType.REVPH, 2, 3)) {
|
||||
assertThrows(
|
||||
AllocationException.class, () -> new Solenoid(0, 3, PneumaticsModuleType.REVPH, 2));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidChannel() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class, () -> new Solenoid(3, PneumaticsModuleType.REVPH, 100));
|
||||
IllegalArgumentException.class, () -> new Solenoid(0, 3, PneumaticsModuleType.REVPH, 100));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToggle() {
|
||||
try (Solenoid solenoid = new Solenoid(3, PneumaticsModuleType.REVPH, 2)) {
|
||||
try (Solenoid solenoid = new Solenoid(0, 3, PneumaticsModuleType.REVPH, 2)) {
|
||||
solenoid.set(true);
|
||||
assertTrue(solenoid.get());
|
||||
|
||||
|
||||
@@ -16,6 +16,6 @@ class CANStatusTest {
|
||||
void canStatusGetDoesntThrow() {
|
||||
HAL.initialize(500, 0);
|
||||
CANStatus status = new CANStatus();
|
||||
assertDoesNotThrow(() -> CANJNI.getCANStatus(status));
|
||||
assertDoesNotThrow(() -> CANJNI.getCANStatus(0, status));
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user