diff --git a/hal/src/main/java/edu/wpi/first/hal/CANAPIJNI.java b/hal/src/main/java/edu/wpi/first/hal/CANAPIJNI.java index 90b1688905..b376b66124 100644 --- a/hal/src/main/java/edu/wpi/first/hal/CANAPIJNI.java +++ b/hal/src/main/java/edu/wpi/first/hal/CANAPIJNI.java @@ -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. * *

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 { *

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 { *

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 { *

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 { *

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 { *

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() {} diff --git a/hal/src/main/java/edu/wpi/first/hal/CANData.java b/hal/src/main/java/edu/wpi/first/hal/CANData.java deleted file mode 100644 index f91e4163bd..0000000000 --- a/hal/src/main/java/edu/wpi/first/hal/CANData.java +++ /dev/null @@ -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; - } -} diff --git a/hal/src/main/java/edu/wpi/first/hal/CTREPCMJNI.java b/hal/src/main/java/edu/wpi/first/hal/CTREPCMJNI.java index 88ba3cebdc..3d2dde69ab 100644 --- a/hal/src/main/java/edu/wpi/first/hal/CTREPCMJNI.java +++ b/hal/src/main/java/edu/wpi/first/hal/CTREPCMJNI.java @@ -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. diff --git a/hal/src/main/java/edu/wpi/first/hal/PortsJNI.java b/hal/src/main/java/edu/wpi/first/hal/PortsJNI.java index e92c9110c4..4a7a290c99 100644 --- a/hal/src/main/java/edu/wpi/first/hal/PortsJNI.java +++ b/hal/src/main/java/edu/wpi/first/hal/PortsJNI.java @@ -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. * diff --git a/hal/src/main/java/edu/wpi/first/hal/PowerDistributionJNI.java b/hal/src/main/java/edu/wpi/first/hal/PowerDistributionJNI.java index 2586e3a85b..0e39cc5473 100644 --- a/hal/src/main/java/edu/wpi/first/hal/PowerDistributionJNI.java +++ b/hal/src/main/java/edu/wpi/first/hal/PowerDistributionJNI.java @@ -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. diff --git a/hal/src/main/java/edu/wpi/first/hal/REVPHJNI.java b/hal/src/main/java/edu/wpi/first/hal/REVPHJNI.java index 29d33664f8..20c22a30ef 100644 --- a/hal/src/main/java/edu/wpi/first/hal/REVPHJNI.java +++ b/hal/src/main/java/edu/wpi/first/hal/REVPHJNI.java @@ -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. diff --git a/hal/src/main/java/edu/wpi/first/hal/can/CANExceptionFactory.java b/hal/src/main/java/edu/wpi/first/hal/can/CANExceptionFactory.java deleted file mode 100644 index d5b5688ce5..0000000000 --- a/hal/src/main/java/edu/wpi/first/hal/can/CANExceptionFactory.java +++ /dev/null @@ -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() {} -} diff --git a/hal/src/main/java/edu/wpi/first/hal/can/CANInvalidBufferException.java b/hal/src/main/java/edu/wpi/first/hal/can/CANInvalidBufferException.java deleted file mode 100644 index a73372e4ed..0000000000 --- a/hal/src/main/java/edu/wpi/first/hal/can/CANInvalidBufferException.java +++ /dev/null @@ -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); - } -} diff --git a/hal/src/main/java/edu/wpi/first/hal/can/CANJNI.java b/hal/src/main/java/edu/wpi/first/hal/can/CANJNI.java index 80dd0e7b4f..171e66987b 100644 --- a/hal/src/main/java/edu/wpi/first/hal/can/CANJNI.java +++ b/hal/src/main/java/edu/wpi/first/hal/can/CANJNI.java @@ -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. diff --git a/hal/src/main/java/edu/wpi/first/hal/can/CANMessageNotAllowedException.java b/hal/src/main/java/edu/wpi/first/hal/can/CANMessageNotAllowedException.java deleted file mode 100644 index 138116a5dc..0000000000 --- a/hal/src/main/java/edu/wpi/first/hal/can/CANMessageNotAllowedException.java +++ /dev/null @@ -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); - } -} diff --git a/hal/src/main/java/edu/wpi/first/hal/can/CANMessageNotFoundException.java b/hal/src/main/java/edu/wpi/first/hal/can/CANMessageNotFoundException.java deleted file mode 100644 index 4c0215dfe9..0000000000 --- a/hal/src/main/java/edu/wpi/first/hal/can/CANMessageNotFoundException.java +++ /dev/null @@ -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); - } -} diff --git a/hal/src/main/java/edu/wpi/first/hal/can/CANNotInitializedException.java b/hal/src/main/java/edu/wpi/first/hal/can/CANNotInitializedException.java deleted file mode 100644 index e2d478e0b9..0000000000 --- a/hal/src/main/java/edu/wpi/first/hal/can/CANNotInitializedException.java +++ /dev/null @@ -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); - } -} diff --git a/hal/src/main/java/edu/wpi/first/hal/can/CANReceiveMessage.java b/hal/src/main/java/edu/wpi/first/hal/can/CANReceiveMessage.java new file mode 100644 index 0000000000..7c93ea3cba --- /dev/null +++ b/hal/src/main/java/edu/wpi/first/hal/can/CANReceiveMessage.java @@ -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; + } +} diff --git a/hal/src/main/java/edu/wpi/first/hal/CANStreamMessage.java b/hal/src/main/java/edu/wpi/first/hal/can/CANStreamMessage.java similarity index 74% rename from hal/src/main/java/edu/wpi/first/hal/CANStreamMessage.java rename to hal/src/main/java/edu/wpi/first/hal/can/CANStreamMessage.java index 56331efdc8..32a9c30cf8 100644 --- a/hal/src/main/java/edu/wpi/first/hal/CANStreamMessage.java +++ b/hal/src/main/java/edu/wpi/first/hal/can/CANStreamMessage.java @@ -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; diff --git a/hal/src/main/java/edu/wpi/first/hal/can/CANStreamOverflowException.java b/hal/src/main/java/edu/wpi/first/hal/can/CANStreamOverflowException.java index 39e3ef46e7..d2c97b1ded 100644 --- a/hal/src/main/java/edu/wpi/first/hal/can/CANStreamOverflowException.java +++ b/hal/src/main/java/edu/wpi/first/hal/can/CANStreamOverflowException.java @@ -4,7 +4,6 @@ package edu.wpi.first.hal.can; -import edu.wpi.first.hal.CANStreamMessage; import java.io.IOException; /** diff --git a/hal/src/main/native/cpp/jni/CANAPIJNI.cpp b/hal/src/main/native/cpp/jni/CANAPIJNI.cpp index 33b3a5f420..486b28b6e8 100644 --- a/hal/src/main/native/cpp/jni/CANAPIJNI.cpp +++ b/hal/src/main/native/cpp/jni/CANAPIJNI.cpp @@ -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(manufacturer), + HAL_InitializeCAN(static_cast(busId), + static_cast(manufacturer), static_cast(deviceId), static_cast(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 arr{env, data, static_cast(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(handle); - JSpan arr{env, data}; + HAL_CANMessage message; + if (!PackCANMessage(env, data, dataLength, flags, &message)) { + return; + } + int32_t status = 0; - HAL_WriteCANPacket(halHandle, reinterpret_cast(arr.data()), - arr.size(), apiId, &status); + HAL_WriteCANPacket(static_cast(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(handle); - JSpan arr{env, data}; + HAL_CANMessage message; + if (!PackCANMessage(env, data, dataLength, flags, &message)) { + return; + } + int32_t status = 0; - HAL_WriteCANPacketRepeating(halHandle, - reinterpret_cast(arr.data()), - arr.size(), apiId, timeoutMs, &status); + HAL_WriteCANPacketRepeating(static_cast(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(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(length), apiId, &status); + HAL_WriteCANRTRFrame(static_cast(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(handle); - JSpan 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(arr.data()), - arr.size(), apiId, &status); + HAL_WriteCANPacket(static_cast(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(handle); - JSpan 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(arr.data()), - arr.size(), apiId, timeoutMs, &status); + HAL_WriteCANPacketRepeating(static_cast(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(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(length), apiId, &status); + HAL_WriteCANRTRFrame(static_cast(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(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(dataTemp)); + env->SetByteArrayRegion(toSetArray, 0, message.message.dataSize, + reinterpret_cast(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(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(dataTemp)); + env->SetByteArrayRegion(toSetArray, 0, message.message.dataSize, + reinterpret_cast(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(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(dataTemp)); + env->SetByteArrayRegion(toSetArray, 0, message.message.dataSize, + reinterpret_cast(message.message.data)); return true; } } // extern "C" diff --git a/hal/src/main/native/cpp/jni/CANJNI.cpp b/hal/src/main/native/cpp/jni/CANJNI.cpp index 40f77ddd5c..f3d56770a6 100644 --- a/hal/src/main/native/cpp/jni/CANJNI.cpp +++ b/hal/src/main/native/cpp/jni/CANJNI.cpp @@ -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 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(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 arr{env, data, static_cast(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(env->GetDirectBufferAddress(messageID)); - uint32_t* timeStampPtr = - reinterpret_cast(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(dataSize)}); + env->SetByteArrayRegion(toSetArray, 0, message.message.dataSize, + reinterpret_cast(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(messageID), - static_cast(messageIDMask), - static_cast(maxMessages), &status); + HAL_CANStreamHandle handle = + HAL_CAN_OpenStreamSession(busId, static_cast(messageId), + static_cast(messageIDMask), + static_cast(maxMessages), &status); if (!CheckStatus(env, status)) { return static_cast(0); @@ -182,14 +214,17 @@ Java_edu_wpi_first_hal_can_CANJNI_readCANStreamSession } } JLocal 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(msg->data)); + env->SetByteArrayRegion( + toSetArray, 0, msg->message.message.dataSize, + reinterpret_cast(msg->message.message.data)); } if (status == HAL_ERR_CANSessionMux_SessionOverrun) { diff --git a/hal/src/main/native/cpp/jni/CTREPCMJNI.cpp b/hal/src/main/native/cpp/jni/CTREPCMJNI.cpp index 8cc4e7db06..6b5fe88c6a 100644 --- a/hal/src/main/native/cpp/jni/CTREPCMJNI.cpp +++ b/hal/src/main/native/cpp/jni/CTREPCMJNI.cpp @@ -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; } diff --git a/hal/src/main/native/cpp/jni/HALUtil.cpp b/hal/src/main/native/cpp/jni/HALUtil.cpp index 192ea1dfee..f33333b919 100644 --- a/hal/src/main/native/cpp/jni/HALUtil.cpp +++ b/hal/src/main/native/cpp/jni/HALUtil.cpp @@ -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, "", "()V"); - } - jobject exception = - env->NewObject(canInvalidBufferExCls, invalidBufConstruct); - env->Throw(static_cast(exception)); - break; - } - case HAL_ERR_CANSessionMux_MessageNotFound: - case kRIOStatusOperationTimedOut: { - static jmethodID messageNotFoundConstruct = nullptr; - if (!messageNotFoundConstruct) { - messageNotFoundConstruct = - env->GetMethodID(canMessageNotFoundExCls, "", "()V"); - } - jobject exception = - env->NewObject(canMessageNotFoundExCls, messageNotFoundConstruct); - env->Throw(static_cast(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, "", "()V"); - } - jobject exception = - env->NewObject(canNotInitializedExCls, notInitConstruct); - env->Throw(static_cast(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(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(env->CallObjectMethod( - canData, func, static_cast(length), static_cast(timestamp))); + canData, func, static_cast(length), static_cast(flags), + static_cast(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(env->CallObjectMethod( canStreamData, func, static_cast(length), - static_cast(messageID), static_cast(timestamp))); + static_cast(messageId), static_cast(timestamp))); return retVal; } diff --git a/hal/src/main/native/cpp/jni/HALUtil.h b/hal/src/main/native/cpp/jni/HALUtil.h index 739e786491..58be7ca3fe 100644 --- a/hal/src/main/native/cpp/jni/HALUtil.h +++ b/hal/src/main/native/cpp/jni/HALUtil.h @@ -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); diff --git a/hal/src/main/native/cpp/jni/PortsJNI.cpp b/hal/src/main/native/cpp/jni/PortsJNI.cpp index 2a86d90e2c..4b588d7b4b 100644 --- a/hal/src/main/native/cpp/jni/PortsJNI.cpp +++ b/hal/src/main/native/cpp/jni/PortsJNI.cpp @@ -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 diff --git a/hal/src/main/native/cpp/jni/PowerDistributionJNI.cpp b/hal/src/main/native/cpp/jni/PowerDistributionJNI.cpp index 1fc245c8e8..83ac85cb57 100644 --- a/hal/src/main/native/cpp/jni/PowerDistributionJNI.cpp +++ b/hal/src/main/native/cpp/jni/PowerDistributionJNI.cpp @@ -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(type), stack.c_str(), - &status); + busId, module, static_cast(type), + stack.c_str(), &status); CheckStatusForceThrow(env, status); return static_cast(handle); } diff --git a/hal/src/main/native/cpp/jni/REVPHJNI.cpp b/hal/src/main/native/cpp/jni/REVPHJNI.cpp index cc687aeeed..d1818dd3f8 100644 --- a/hal/src/main/native/cpp/jni/REVPHJNI.cpp +++ b/hal/src/main/native/cpp/jni/REVPHJNI.cpp @@ -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; } diff --git a/hal/src/main/native/include/hal/CAN.h b/hal/src/main/native/include/hal/CAN.h index e61ddc2ae0..c610be8c41 100644 --- a/hal/src/main/native/include/hal/CAN.h +++ b/hal/src/main/native/include/hal/CAN.h @@ -4,6 +4,8 @@ #pragma once +#include +#include #include /** @@ -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); diff --git a/hal/src/main/native/include/hal/CANAPI.h b/hal/src/main/native/include/hal/CANAPI.h index 005aa1bc19..879f5a64bb 100644 --- a/hal/src/main/native/include/hal/CANAPI.h +++ b/hal/src/main/native/include/hal/CANAPI.h @@ -6,6 +6,7 @@ #include +#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" diff --git a/hal/src/main/native/include/hal/CANAPITypes.h b/hal/src/main/native/include/hal/CANAPITypes.h index 7cfe93b4c4..baec978727 100644 --- a/hal/src/main/native/include/hal/CANAPITypes.h +++ b/hal/src/main/native/include/hal/CANAPITypes.h @@ -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; +}; /** @} */ diff --git a/hal/src/main/native/include/hal/CTREPCM.h b/hal/src/main/native/include/hal/CTREPCM.h index fc7c46e084..ff0e43f85b 100644 --- a/hal/src/main/native/include/hal/CTREPCM.h +++ b/hal/src/main/native/include/hal/CTREPCM.h @@ -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); diff --git a/hal/src/main/native/include/hal/Ports.h b/hal/src/main/native/include/hal/Ports.h index 4536b6557d..fb5fb021fd 100644 --- a/hal/src/main/native/include/hal/Ports.h +++ b/hal/src/main/native/include/hal/Ports.h @@ -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. * diff --git a/hal/src/main/native/include/hal/PowerDistribution.h b/hal/src/main/native/include/hal/PowerDistribution.h index 757d92f7d9..f470c1f47c 100644 --- a/hal/src/main/native/include/hal/PowerDistribution.h +++ b/hal/src/main/native/include/hal/PowerDistribution.h @@ -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( diff --git a/hal/src/main/native/include/hal/REVPH.h b/hal/src/main/native/include/hal/REVPH.h index 797ecf5752..ae2c7f962c 100644 --- a/hal/src/main/native/include/hal/REVPH.h +++ b/hal/src/main/native/include/hal/REVPH.h @@ -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); diff --git a/hal/src/main/native/include/hal/Types.h b/hal/src/main/native/include/hal/Types.h index 265bf88fad..3c26462558 100644 --- a/hal/src/main/native/include/hal/Types.h +++ b/hal/src/main/native/include/hal/Types.h @@ -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 diff --git a/hal/src/main/native/include/hal/simulation/CanData.h b/hal/src/main/native/include/hal/simulation/CanData.h index 2590162bea..4b66589129 100644 --- a/hal/src/main/native/include/hal/simulation/CanData.h +++ b/hal/src/main/native/include/hal/simulation/CanData.h @@ -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); diff --git a/hal/src/main/native/sim/CAN.cpp b/hal/src/main/native/sim/CAN.cpp index 93a422b5dd..329929b045 100644 --- a/hal/src/main/native/sim/CAN.cpp +++ b/hal/src/main/native/sim/CAN.cpp @@ -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" diff --git a/hal/src/main/native/sim/CANAPI.cpp b/hal/src/main/native/sim/CANAPI.cpp index eaa42fa2a1..76a4e3dcb2 100644 --- a/hal/src/main/native/sim/CANAPI.cpp +++ b/hal/src/main/native/sim/CANAPI.cpp @@ -4,34 +4,31 @@ #include "hal/CANAPI.h" +#include #include #include +#include +#include -#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 periodicSends; wpi::mutex receivesMutex; - wpi::SmallDenseMap receives; + wpi::SmallDenseMap 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(); 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(timeoutMs)) { + uint64_t now = wpi::Now(); + if (now - i->second.timeStamp > + (static_cast(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" diff --git a/hal/src/main/native/sim/CTREPCM.cpp b/hal/src/main/native/sim/CTREPCM.cpp index 0ac921f040..0b6dc384db 100644 --- a/hal/src/main/native/sim/CTREPCM.cpp +++ b/hal/src/main/native/sim/CTREPCM.cpp @@ -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(); diff --git a/hal/src/main/native/sim/Ports.cpp b/hal/src/main/native/sim/Ports.cpp index 4cd622085a..d4082ad419 100644 --- a/hal/src/main/native/sim/Ports.cpp +++ b/hal/src/main/native/sim/Ports.cpp @@ -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; } diff --git a/hal/src/main/native/sim/PortsInternal.h b/hal/src/main/native/sim/PortsInternal.h index e1562fb95e..893c608610 100644 --- a/hal/src/main/native/sim/PortsInternal.h +++ b/hal/src/main/native/sim/PortsInternal.h @@ -7,6 +7,7 @@ #include namespace hal { +constexpr int32_t kNumCanBuses = 2; constexpr int32_t kAccelerometers = 1; constexpr int32_t kNumAccumulators = 2; constexpr int32_t kNumAnalogInputs = 8; diff --git a/hal/src/main/native/sim/PowerDistribution.cpp b/hal/src/main/native/sim/PowerDistribution.cpp index 25a0d36ccc..44956ab6fc 100644 --- a/hal/src/main/native/sim/PowerDistribution.cpp +++ b/hal/src/main/native/sim/PowerDistribution.cpp @@ -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); diff --git a/hal/src/main/native/sim/REVPH.cpp b/hal/src/main/native/sim/REVPH.cpp index 89fda1ad35..1281433b31 100644 --- a/hal/src/main/native/sim/REVPH.cpp +++ b/hal/src/main/native/sim/REVPH.cpp @@ -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(); diff --git a/hal/src/main/native/systemcore/CAN.cpp b/hal/src/main/native/systemcore/CAN.cpp index cd7d3d533f..0c3aa82a4e 100644 --- a/hal/src/main/native/systemcore/CAN.cpp +++ b/hal/src/main/native/systemcore/CAN.cpp @@ -21,14 +21,13 @@ #include #include +#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>> timers; // ms to bus mask/packet - wpi::DenseMap, NUM_CAN_BUSES>> + wpi::DenseMap, hal::kNumCanBuses>> timedFrames; // packet to time - wpi::DenseMap> packetToTime; + wpi::DenseMap> 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 readFrames[NUM_CAN_BUSES]; + wpi::DenseMap 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(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(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; diff --git a/hal/src/main/native/systemcore/CANAPI.cpp b/hal/src/main/native/systemcore/CANAPI.cpp index fdcefa0d20..0f038c2b57 100644 --- a/hal/src/main/native/systemcore/CANAPI.cpp +++ b/hal/src/main/native/systemcore/CANAPI.cpp @@ -12,6 +12,7 @@ #include #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 periodicSends; wpi::mutex receivesMutex; - wpi::SmallDenseMap receives; + wpi::SmallDenseMap 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(); 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(timeoutMs)) { + uint64_t now = wpi::Now(); + if (now - i->second.timeStamp > + (static_cast(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" diff --git a/hal/src/main/native/systemcore/CTREPCM.cpp b/hal/src/main/native/systemcore/CTREPCM.cpp index 4c104da5e6..41259d7ae4 100644 --- a/hal/src/main/native/systemcore/CTREPCM.cpp +++ b/hal/src/main/native/systemcore/CTREPCM.cpp @@ -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(durMs) / 10, static_cast(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" diff --git a/hal/src/main/native/systemcore/CTREPDP.cpp b/hal/src/main/native/systemcore/CTREPDP.cpp index e9da90c921..2c3236b2cc 100644 --- a/hal/src/main/native/systemcore/CTREPDP.cpp +++ b/hal/src/main/native/systemcore/CTREPDP.cpp @@ -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(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(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(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(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(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(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(pdpStatus.bits.chan13_h8) << 2) | diff --git a/hal/src/main/native/systemcore/CTREPDP.h b/hal/src/main/native/systemcore/CTREPDP.h index 99606e0575..201e31cd22 100644 --- a/hal/src/main/native/systemcore/CTREPDP.h +++ b/hal/src/main/native/systemcore/CTREPDP.h @@ -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); /** diff --git a/hal/src/main/native/systemcore/Ports.cpp b/hal/src/main/native/systemcore/Ports.cpp index 22cc829376..55176c60dc 100644 --- a/hal/src/main/native/systemcore/Ports.cpp +++ b/hal/src/main/native/systemcore/Ports.cpp @@ -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; } diff --git a/hal/src/main/native/systemcore/PortsInternal.h b/hal/src/main/native/systemcore/PortsInternal.h index 4d42fa4ec4..8bdba18a24 100644 --- a/hal/src/main/native/systemcore/PortsInternal.h +++ b/hal/src/main/native/systemcore/PortsInternal.h @@ -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; diff --git a/hal/src/main/native/systemcore/PowerDistribution.cpp b/hal/src/main/native/systemcore/PowerDistribution.cpp index 580aa9005a..a136a97fa8 100644 --- a/hal/src/main/native/systemcore/PowerDistribution.cpp +++ b/hal/src/main/native/systemcore/PowerDistribution.cpp @@ -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(pdhHandle); } @@ -65,13 +65,13 @@ HAL_PowerDistributionHandle HAL_InitializePowerDistribution( moduleNumber = 0; } return static_cast( - 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_InitializeREVPDH(moduleNumber, allocationLocation, status)); + HAL_InitializeREVPDH(busId, moduleNumber, allocationLocation, status)); } } diff --git a/hal/src/main/native/systemcore/REVPDH.cpp b/hal/src/main/native/systemcore/REVPDH.cpp index fc9f7c1778..ebb7511318 100644 --- a/hal/src/main/native/systemcore/REVPDH.cpp +++ b/hal/src/main/native/systemcore/REVPDH.cpp @@ -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); diff --git a/hal/src/main/native/systemcore/REVPDH.h b/hal/src/main/native/systemcore/REVPDH.h index 0046455339..5d57a7853b 100644 --- a/hal/src/main/native/systemcore/REVPDH.h +++ b/hal/src/main/native/systemcore/REVPDH.h @@ -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); diff --git a/hal/src/main/native/systemcore/REVPH.cpp b/hal/src/main/native/systemcore/REVPH.cpp index 37b3865988..9bbf51014e 100644 --- a/hal/src/main/native/systemcore/REVPH.cpp +++ b/hal/src/main/native/systemcore/REVPH.cpp @@ -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, diff --git a/hal/src/test/native/cpp/can/CANTest.cpp b/hal/src/test/native/cpp/can/CANTest.cpp index 4a0ad691d3..69075db608 100644 --- a/hal/src/test/native/cpp/can/CANTest.cpp +++ b/hal/src/test/native/cpp/can/CANTest.cpp @@ -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 #include #include @@ -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 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* paramI = reinterpret_cast*>(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); diff --git a/hal/src/test/native/cpp/mockdata/PCMDataTest.cpp b/hal/src/test/native/cpp/mockdata/PCMDataTest.cpp index d3c5a8021b..e7a9b4196d 100644 --- a/hal/src/test/native/cpp/mockdata/PCMDataTest.cpp +++ b/hal/src/test/native/cpp/mockdata/PCMDataTest.cpp @@ -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()); diff --git a/hal/src/test/native/cpp/mockdata/PDPDataTest.cpp b/hal/src/test/native/cpp/mockdata/PDPDataTest.cpp index 14a36843ed..7478ae3775 100644 --- a/hal/src/test/native/cpp/mockdata/PDPDataTest.cpp +++ b/hal/src/test/native/cpp/mockdata/PDPDataTest.cpp @@ -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()); } diff --git a/wpilibc/src/main/native/cpp/CAN.cpp b/wpilibc/src/main/native/cpp/CAN.cpp index a08d16acce..3e57370d38 100644 --- a/wpilibc/src/main/native/cpp/CAN.cpp +++ b/wpilibc/src/main/native/cpp/CAN.cpp @@ -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(deviceManufacturer), deviceId, + busId, static_cast(deviceManufacturer), deviceId, static_cast(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(); -} diff --git a/wpilibc/src/main/native/cpp/Compressor.cpp b/wpilibc/src/main/native/cpp/Compressor.cpp index 761acf3b3a..c5b9d1d909 100644 --- a/wpilibc/src/main/native/cpp/Compressor.cpp +++ b/wpilibc/src/main/native/cpp/Compressor.cpp @@ -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) { diff --git a/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp b/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp index fb51203039..e03e408810 100644 --- a/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp +++ b/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp @@ -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) { diff --git a/wpilibc/src/main/native/cpp/PneumaticHub.cpp b/wpilibc/src/main/native/cpp/PneumaticHub.cpp index 004bad29e5..c7b8d43f25 100644 --- a/wpilibc/src/main/native/cpp/PneumaticHub.cpp +++ b/wpilibc/src/main/native/cpp/PneumaticHub.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -39,26 +40,31 @@ units::volt_t PSIToVolts(units::pounds_per_square_inch_t pressure, } wpi::mutex PneumaticHub::m_handleLock; -std::unique_ptr>> - PneumaticHub::m_handleMap = nullptr; +std::unique_ptr>[]> + PneumaticHub::m_handleMaps = nullptr; // Always called under lock, so we can avoid the double lock from the magic // static -std::weak_ptr& PneumaticHub::GetDataStore(int module) { - if (!m_handleMap) { - m_handleMap = std::make_unique< - wpi::DenseMap>>(); +std::weak_ptr& 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>[]>(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{this, wpi::NullDeleter()}; @@ -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 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(module, stackTrace.c_str()); + m_dataStore = + std::make_shared(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 PneumaticHub::GetForModule(int module) { +std::shared_ptr 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 = res.lock(); if (!dataStore) { - dataStore = std::make_shared(module, stackTrace.c_str()); + dataStore = std::make_shared(busId, module, stackTrace.c_str()); res = dataStore; } diff --git a/wpilibc/src/main/native/cpp/PneumaticsBase.cpp b/wpilibc/src/main/native/cpp/PneumaticsBase.cpp index 78c5f0dd72..9c024f4a33 100644 --- a/wpilibc/src/main/native/cpp/PneumaticsBase.cpp +++ b/wpilibc/src/main/native/cpp/PneumaticsBase.cpp @@ -29,11 +29,11 @@ static_assert( HAL_REVPHCompressorConfigType::HAL_REVPHCompressorConfigType_kHybrid); std::shared_ptr 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(moduleType)); diff --git a/wpilibc/src/main/native/cpp/PneumaticsControlModule.cpp b/wpilibc/src/main/native/cpp/PneumaticsControlModule.cpp index cccd1c2896..f7dd7ea264 100644 --- a/wpilibc/src/main/native/cpp/PneumaticsControlModule.cpp +++ b/wpilibc/src/main/native/cpp/PneumaticsControlModule.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -23,28 +24,32 @@ using namespace frc; wpi::mutex PneumaticsControlModule::m_handleLock; std::unique_ptr< - wpi::DenseMap>> - PneumaticsControlModule::m_handleMap = nullptr; + wpi::DenseMap>[]> + PneumaticsControlModule::m_handleMaps = nullptr; // Always called under lock, so we can avoid the double lock from the magic // static std::weak_ptr& -PneumaticsControlModule::GetDataStore(int module) { - if (!m_handleMap) { - m_handleMap = std::make_unique>>(); +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>[]>(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{this, wpi::NullDeleter()}; } @@ -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(module, stackTrace.c_str()); + m_dataStore = + std::make_shared(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 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 = res.lock(); if (!dataStore) { - dataStore = std::make_shared(module, stackTrace.c_str()); + dataStore = std::make_shared(busId, module, stackTrace.c_str()); res = dataStore; } diff --git a/wpilibc/src/main/native/cpp/PowerDistribution.cpp b/wpilibc/src/main/native/cpp/PowerDistribution.cpp index 2b6077f2bc..28c08eb91b 100644 --- a/wpilibc/src/main/native/cpp/PowerDistribution.cpp +++ b/wpilibc/src/main/native/cpp/PowerDistribution.cpp @@ -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(moduleType), stack.c_str(), - &status); + busId, module, static_cast(moduleType), + stack.c_str(), &status); FRC_CheckErrorStatus(status, "Module {}", module); m_module = HAL_GetPowerDistributionModuleNumber(m_handle, &status); FRC_ReportError(status, "Module {}", module); diff --git a/wpilibc/src/main/native/cpp/RobotController.cpp b/wpilibc/src/main/native/cpp/RobotController.cpp index 72483e14df..57200d30e8 100644 --- a/wpilibc/src/main/native/cpp/RobotController.cpp +++ b/wpilibc/src/main/native/cpp/RobotController.cpp @@ -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(busOffCount), static_cast(txFullCount), static_cast(receiveErrorCount), diff --git a/wpilibc/src/main/native/cpp/Solenoid.cpp b/wpilibc/src/main/native/cpp/Solenoid.cpp index 8096955f8a..660d56a403 100644 --- a/wpilibc/src/main/native/cpp/Solenoid.cpp +++ b/wpilibc/src/main/native/cpp/Solenoid.cpp @@ -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() { diff --git a/wpilibc/src/main/native/include/frc/CAN.h b/wpilibc/src/main/native/include/frc/CAN.h index c9c35f51bd..f3029e3eb2 100644 --- a/wpilibc/src/main/native/include/frc/CAN.h +++ b/wpilibc/src/main/native/include/frc/CAN.h @@ -9,14 +9,6 @@ #include 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; diff --git a/wpilibc/src/main/native/include/frc/Compressor.h b/wpilibc/src/main/native/include/frc/Compressor.h index d9bff84100..08dac7fc49 100644 --- a/wpilibc/src/main/native/include/frc/Compressor.h +++ b/wpilibc/src/main/native/include/frc/Compressor.h @@ -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; diff --git a/wpilibc/src/main/native/include/frc/DoubleSolenoid.h b/wpilibc/src/main/native/include/frc/DoubleSolenoid.h index e31fb8a290..8fa5ad72ba 100644 --- a/wpilibc/src/main/native/include/frc/DoubleSolenoid.h +++ b/wpilibc/src/main/native/include/frc/DoubleSolenoid.h @@ -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; diff --git a/wpilibc/src/main/native/include/frc/PneumaticHub.h b/wpilibc/src/main/native/include/frc/PneumaticHub.h index 37f88be517..2facb3f9ff 100644 --- a/wpilibc/src/main/native/include/frc/PneumaticHub.h +++ b/wpilibc/src/main/native/include/frc/PneumaticHub.h @@ -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 GetForModule(int module); + static std::shared_ptr GetForModule(int busId, int module); std::shared_ptr m_dataStore; HAL_REVPHHandle m_handle; int m_module; static wpi::mutex m_handleLock; - static std::unique_ptr>> - m_handleMap; - static std::weak_ptr& GetDataStore(int module); + static std::unique_ptr>[]> + m_handleMaps; + static std::weak_ptr& GetDataStore(int busId, int module); }; } // namespace frc diff --git a/wpilibc/src/main/native/include/frc/PneumaticsBase.h b/wpilibc/src/main/native/include/frc/PneumaticsBase.h index 606745e5e2..f28c6bea28 100644 --- a/wpilibc/src/main/native/include/frc/PneumaticsBase.h +++ b/wpilibc/src/main/native/include/frc/PneumaticsBase.h @@ -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 GetForType( - int module, PneumaticsModuleType moduleType); + int busId, int module, PneumaticsModuleType moduleType); /** * For internal use to get the default for a specific type. diff --git a/wpilibc/src/main/native/include/frc/PneumaticsControlModule.h b/wpilibc/src/main/native/include/frc/PneumaticsControlModule.h index c51e9672c9..b048721bfc 100644 --- a/wpilibc/src/main/native/include/frc/PneumaticsControlModule.h +++ b/wpilibc/src/main/native/include/frc/PneumaticsControlModule.h @@ -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 GetForModule(int module); + static std::shared_ptr GetForModule(int busId, int module); std::shared_ptr m_dataStore; HAL_CTREPCMHandle m_handle; int m_module; static wpi::mutex m_handleLock; - static std::unique_ptr>> - m_handleMap; - static std::weak_ptr& GetDataStore(int module); + static std::unique_ptr>[]> + m_handleMaps; + static std::weak_ptr& GetDataStore(int busId, int module); }; } // namespace frc diff --git a/wpilibc/src/main/native/include/frc/PowerDistribution.h b/wpilibc/src/main/native/include/frc/PowerDistribution.h index 8d647af542..fbcfe765c6 100644 --- a/wpilibc/src/main/native/include/frc/PowerDistribution.h +++ b/wpilibc/src/main/native/include/frc/PowerDistribution.h @@ -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; diff --git a/wpilibc/src/main/native/include/frc/RobotController.h b/wpilibc/src/main/native/include/frc/RobotController.h index 272ae4a490..d696f1f171 100644 --- a/wpilibc/src/main/native/include/frc/RobotController.h +++ b/wpilibc/src/main/native/include/frc/RobotController.h @@ -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 m_timeSource; diff --git a/wpilibc/src/main/native/include/frc/Solenoid.h b/wpilibc/src/main/native/include/frc/Solenoid.h index ba10a73f20..0c8e7e9836 100644 --- a/wpilibc/src/main/native/include/frc/Solenoid.h +++ b/wpilibc/src/main/native/include/frc/Solenoid.h @@ -28,19 +28,21 @@ class Solenoid : public wpi::Sendable, public wpi::SendableHelper { /** * 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; diff --git a/wpilibc/src/test/native/cpp/DoubleSolenoidTestCTRE.cpp b/wpilibc/src/test/native/cpp/DoubleSolenoidTestCTRE.cpp index 7534945882..ea5eb94ee9 100644 --- a/wpilibc/src/test/native/cpp/DoubleSolenoidTestCTRE.cpp +++ b/wpilibc/src/test/native/cpp/DoubleSolenoidTestCTRE.cpp @@ -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 diff --git a/wpilibc/src/test/native/cpp/DoubleSolenoidTestREV.cpp b/wpilibc/src/test/native/cpp/DoubleSolenoidTestREV.cpp index 336d3170f9..94b269d1bf 100644 --- a/wpilibc/src/test/native/cpp/DoubleSolenoidTestREV.cpp +++ b/wpilibc/src/test/native/cpp/DoubleSolenoidTestREV.cpp @@ -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 diff --git a/wpilibc/src/test/native/cpp/SolenoidTestCTRE.cpp b/wpilibc/src/test/native/cpp/SolenoidTestCTRE.cpp index f30a97646a..7faf31b097 100644 --- a/wpilibc/src/test/native/cpp/SolenoidTestCTRE.cpp +++ b/wpilibc/src/test/native/cpp/SolenoidTestCTRE.cpp @@ -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()); diff --git a/wpilibc/src/test/native/cpp/SolenoidTestREV.cpp b/wpilibc/src/test/native/cpp/SolenoidTestREV.cpp index 3f3dc404b7..c7462314ef 100644 --- a/wpilibc/src/test/native/cpp/SolenoidTestREV.cpp +++ b/wpilibc/src/test/native/cpp/SolenoidTestREV.cpp @@ -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()); diff --git a/wpilibc/src/test/native/cpp/simulation/CTREPCMSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/CTREPCMSimTest.cpp index 0d3e6ecc06..c77cef4ee7 100644 --- a/wpilibc/src/test/native/cpp/simulation/CTREPCMSimTest.cpp +++ b/wpilibc/src/test/native/cpp/simulation/CTREPCMSimTest.cpp @@ -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(); diff --git a/wpilibc/src/test/native/cpp/simulation/PDPSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/PDPSimTest.cpp index 99652a9496..7964fe22e9 100644 --- a/wpilibc/src/test/native/cpp/simulation/PDPSimTest.cpp +++ b/wpilibc/src/test/native/cpp/simulation/PDPSimTest.cpp @@ -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 diff --git a/wpilibc/src/test/native/cpp/simulation/REVPHSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/REVPHSimTest.cpp index 952107ba22..3c2fb41352 100644 --- a/wpilibc/src/test/native/cpp/simulation/REVPHSimTest.cpp +++ b/wpilibc/src/test/native/cpp/simulation/REVPHSimTest.cpp @@ -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(); diff --git a/wpilibcExamples/src/main/cpp/examples/CANPDP/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/examples/CANPDP/cpp/Robot.cpp index b22c27cf90..e430e13796 100644 --- a/wpilibcExamples/src/main/cpp/examples/CANPDP/cpp/Robot.cpp +++ b/wpilibcExamples/src/main/cpp/examples/CANPDP/cpp/Robot.cpp @@ -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 diff --git a/wpilibcExamples/src/main/cpp/examples/HatchbotInlined/cpp/subsystems/HatchSubsystem.cpp b/wpilibcExamples/src/main/cpp/examples/HatchbotInlined/cpp/subsystems/HatchSubsystem.cpp index 449465bb49..40829c26db 100644 --- a/wpilibcExamples/src/main/cpp/examples/HatchbotInlined/cpp/subsystems/HatchSubsystem.cpp +++ b/wpilibcExamples/src/main/cpp/examples/HatchbotInlined/cpp/subsystems/HatchSubsystem.cpp @@ -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() { diff --git a/wpilibcExamples/src/main/cpp/examples/HatchbotTraditional/cpp/subsystems/HatchSubsystem.cpp b/wpilibcExamples/src/main/cpp/examples/HatchbotTraditional/cpp/subsystems/HatchSubsystem.cpp index 975141fe1c..62ef064ed1 100644 --- a/wpilibcExamples/src/main/cpp/examples/HatchbotTraditional/cpp/subsystems/HatchSubsystem.cpp +++ b/wpilibcExamples/src/main/cpp/examples/HatchbotTraditional/cpp/subsystems/HatchSubsystem.cpp @@ -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() { diff --git a/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Intake.h b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Intake.h index 111353a0f5..50b2304220 100644 --- a/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Intake.h +++ b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Intake.h @@ -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]}; }; diff --git a/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Pneumatics.h b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Pneumatics.h index 0c1fee92a9..80642c8a71 100644 --- a/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Pneumatics.h +++ b/wpilibcExamples/src/main/cpp/examples/RapidReactCommandBot/include/subsystems/Pneumatics.h @@ -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}; }; diff --git a/wpilibcExamples/src/main/cpp/examples/Solenoid/include/Robot.h b/wpilibcExamples/src/main/cpp/examples/Solenoid/include/Robot.h index 46920ce620..12d640223d 100644 --- a/wpilibcExamples/src/main/cpp/examples/Solenoid/include/Robot.h +++ b/wpilibcExamples/src/main/cpp/examples/Solenoid/include/Robot.h @@ -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; diff --git a/wpilibcExamples/src/main/cpp/examples/UnitTest/include/subsystems/Intake.h b/wpilibcExamples/src/main/cpp/examples/UnitTest/include/subsystems/Intake.h index 20cf1b6320..ab2b06d857 100644 --- a/wpilibcExamples/src/main/cpp/examples/UnitTest/include/subsystems/Intake.h +++ b/wpilibcExamples/src/main/cpp/examples/UnitTest/include/subsystems/Intake.h @@ -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}; }; diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/CAN.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/CAN.java index c1d5eba453..086e870be0 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/CAN.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/CAN.java @@ -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); } } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Compressor.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Compressor.java index f68d83fbfd..882aed2d0b 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Compressor.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Compressor.java @@ -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 diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DoubleSolenoid.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DoubleSolenoid.java index 9b83be9e24..b01030f1b7 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DoubleSolenoid.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DoubleSolenoid.java @@ -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; diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticHub.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticHub.java index 8dea010d15..09fe5b55ae 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticHub.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticHub.java @@ -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 m_handleMap = new HashMap<>(); + @SuppressWarnings({"unchecked", "rawtypes"}) + private static final Map[] m_handleMaps = + (Map[]) 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 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; } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticsBase.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticsBase.java index 27a3587f33..25bc4ec6bc 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticsBase.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticsBase.java @@ -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); }; } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticsControlModule.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticsControlModule.java index 65124e6ea6..a0b0d5751b 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticsControlModule.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticsControlModule.java @@ -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 m_handleMap = new HashMap<>(); + @SuppressWarnings({"unchecked", "rawtypes"}) + private static final Map[] m_handleMaps = + (Map[]) 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 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; } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/PowerDistribution.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/PowerDistribution.java index c73fe93583..d4be6f6d98 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/PowerDistribution.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/PowerDistribution.java @@ -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. * *

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) { diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotController.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotController.java index 356854f356..e54038e921 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotController.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotController.java @@ -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; } } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Solenoid.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Solenoid.java index 8008ec4a77..bf7f0b18c1 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Solenoid.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Solenoid.java @@ -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; diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/DoubleSolenoidTestCTRE.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/DoubleSolenoidTestCTRE.java index 9e2971eebb..4a1e4ba6d4 100644 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/DoubleSolenoidTestCTRE.java +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/DoubleSolenoidTestCTRE.java @@ -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)); } } diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/DoubleSolenoidTestREV.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/DoubleSolenoidTestREV.java index 15e88c5449..c8480e3c6b 100644 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/DoubleSolenoidTestREV.java +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/DoubleSolenoidTestREV.java @@ -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)); } } diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/PowerDistributionTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/PowerDistributionTest.java index a76323b6d3..86866c9630 100644 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/PowerDistributionTest.java +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/PowerDistributionTest.java @@ -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++) { diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/SolenoidTestCTRE.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/SolenoidTestCTRE.java index 1712046786..8c712a5fb2 100644 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/SolenoidTestCTRE.java +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/SolenoidTestCTRE.java @@ -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()); diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/SolenoidTestREV.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/SolenoidTestREV.java index eb327d4dc7..b0d80ad3f7 100644 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/SolenoidTestREV.java +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/SolenoidTestREV.java @@ -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()); diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/can/CANStatusTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/can/CANStatusTest.java index 71104fc065..0d4efa6138 100644 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/can/CANStatusTest.java +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/can/CANStatusTest.java @@ -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)); } } diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/canpdp/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/canpdp/Robot.java index 796bf0f76e..fd25d96b07 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/canpdp/Robot.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/canpdp/Robot.java @@ -13,7 +13,7 @@ import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; * via CAN. The information will be displayed under variables through the SmartDashboard. */ public class Robot extends TimedRobot { - private final PowerDistribution m_pdp = new PowerDistribution(); + private final PowerDistribution m_pdp = new PowerDistribution(0); public Robot() { // Put the PDP itself to the dashboard diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbotinlined/subsystems/HatchSubsystem.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbotinlined/subsystems/HatchSubsystem.java index ec489be1ed..b149a60958 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbotinlined/subsystems/HatchSubsystem.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbotinlined/subsystems/HatchSubsystem.java @@ -18,6 +18,7 @@ import edu.wpi.first.wpilibj2.command.SubsystemBase; public class HatchSubsystem extends SubsystemBase { private final DoubleSolenoid m_hatchSolenoid = new DoubleSolenoid( + 0, PneumaticsModuleType.CTREPCM, HatchConstants.kHatchSolenoidPorts[0], HatchConstants.kHatchSolenoidPorts[1]); diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbottraditional/subsystems/HatchSubsystem.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbottraditional/subsystems/HatchSubsystem.java index fcef9e244f..b515ff6bf1 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbottraditional/subsystems/HatchSubsystem.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbottraditional/subsystems/HatchSubsystem.java @@ -17,6 +17,7 @@ import edu.wpi.first.wpilibj2.command.SubsystemBase; public class HatchSubsystem extends SubsystemBase { private final DoubleSolenoid m_hatchSolenoid = new DoubleSolenoid( + 0, PneumaticsModuleType.CTREPCM, HatchConstants.kHatchSolenoidPorts[0], HatchConstants.kHatchSolenoidPorts[1]); diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Intake.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Intake.java index d6b841962a..5fa19a14aa 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Intake.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Intake.java @@ -9,6 +9,7 @@ import static edu.wpi.first.wpilibj.examples.rapidreactcommandbot.Constants.Inta import edu.wpi.first.epilogue.Logged; import edu.wpi.first.wpilibj.DoubleSolenoid; import edu.wpi.first.wpilibj.PneumaticsModuleType; +import edu.wpi.first.wpilibj.examples.rapidreactcommandbot.Constants.IntakeConstants; import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax; import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.SubsystemBase; @@ -20,6 +21,7 @@ public class Intake extends SubsystemBase { // Double solenoid connected to two channels of a PCM with the default CAN ID private final DoubleSolenoid m_pistons = new DoubleSolenoid( + 0, PneumaticsModuleType.CTREPCM, IntakeConstants.kSolenoidPorts[0], IntakeConstants.kSolenoidPorts[1]); diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Pneumatics.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Pneumatics.java index fd35d5f64a..b71ae0c3d5 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Pneumatics.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/subsystems/Pneumatics.java @@ -25,7 +25,7 @@ public class Pneumatics extends SubsystemBase { new AnalogPotentiometer(/* the AnalogIn port*/ 2, kScale, kOffset); // Compressor connected to a PCM with a default CAN ID (0) - private final Compressor m_compressor = new Compressor(PneumaticsModuleType.CTREPCM); + private final Compressor m_compressor = new Compressor(0, PneumaticsModuleType.CTREPCM); /** * Query the analog pressure sensor. diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/solenoid/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/solenoid/Robot.java index babff17e80..2f22836af1 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/solenoid/Robot.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/solenoid/Robot.java @@ -28,15 +28,15 @@ public class Robot extends TimedRobot { // Solenoid corresponds to a single solenoid. // In this case, it's connected to channel 0 of a PH with the default CAN ID. - private final Solenoid m_solenoid = new Solenoid(PneumaticsModuleType.REVPH, 0); + private final Solenoid m_solenoid = new Solenoid(0, 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. private final DoubleSolenoid m_doubleSolenoid = - new DoubleSolenoid(PneumaticsModuleType.REVPH, 1, 2); + new DoubleSolenoid(0, PneumaticsModuleType.REVPH, 1, 2); // Compressor connected to a PH with a default CAN ID (1) - private final Compressor m_compressor = new Compressor(PneumaticsModuleType.REVPH); + private final Compressor m_compressor = new Compressor(0, PneumaticsModuleType.REVPH); static final int kSolenoidButton = 1; static final int kDoubleSolenoidForwardButton = 2; diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/unittest/subsystems/Intake.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/unittest/subsystems/Intake.java index e84a6079a6..d4d571b170 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/unittest/subsystems/Intake.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/unittest/subsystems/Intake.java @@ -17,6 +17,7 @@ public class Intake implements AutoCloseable { m_motor = new PWMSparkMax(IntakeConstants.kMotorPort); m_piston = new DoubleSolenoid( + 0, PneumaticsModuleType.CTREPCM, IntakeConstants.kPistonFwdChannel, IntakeConstants.kPistonRevChannel);