001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.wpilibj; 006 007import edu.wpi.first.hal.CANAPIJNI; 008import edu.wpi.first.hal.CANAPITypes; 009import edu.wpi.first.hal.HAL; 010import edu.wpi.first.hal.can.CANReceiveMessage; 011import java.io.Closeable; 012 013/** 014 * High level class for interfacing with CAN devices conforming to the standard CAN spec. 015 * 016 * <p>No packets that can be sent gets blocked by the RoboRIO, so all methods work identically in 017 * all robot modes. 018 * 019 * <p>All methods are thread safe, however the CANData object passed into the read methods and the 020 * byte[] passed into the write methods need to not be modified for the duration of their respective 021 * calls. 022 */ 023public class CAN implements Closeable { 024 /** Team manufacturer. */ 025 public static final int kTeamManufacturer = CANAPITypes.CANManufacturer.kTeamUse.id; 026 027 /** Team device type. */ 028 public static final int kTeamDeviceType = CANAPITypes.CANDeviceType.kMiscellaneous.id; 029 030 private final int m_handle; 031 032 /** 033 * Create a new CAN communication interface with the specific device ID. This uses the team 034 * manufacturer and device types. The device ID is 6 bits (0-63). 035 * 036 * @param busId The bus ID 037 * @param deviceId The device id 038 */ 039 public CAN(int busId, int deviceId) { 040 this(busId, deviceId, kTeamManufacturer, kTeamDeviceType); 041 } 042 043 /** 044 * Create a new CAN communication interface with a specific device ID, manufacturer and device 045 * type. The device ID is 6 bits, the manufacturer is 8 bits, and the device type is 5 bits. 046 * 047 * @param busId The bus ID 048 * @param deviceId The device ID 049 * @param deviceManufacturer The device manufacturer 050 * @param deviceType The device type 051 */ 052 public CAN(int busId, int deviceId, int deviceManufacturer, int deviceType) { 053 m_handle = CANAPIJNI.initializeCAN(busId, deviceManufacturer, deviceId, deviceType); 054 HAL.reportUsage("CAN[" + deviceType + "][" + deviceManufacturer + "][" + deviceId + "]", ""); 055 } 056 057 /** Closes the CAN communication. */ 058 @Override 059 public void close() { 060 if (m_handle != 0) { 061 CANAPIJNI.cleanCAN(m_handle); 062 } 063 } 064 065 /** 066 * Write a packet to the CAN device with a specific ID. This ID is 10 bits. 067 * 068 * @param apiId The API ID to write. 069 * @param data The data to write 070 * @param dataLength The data length 071 * @param flags The flags 072 */ 073 public void writePacket(int apiId, byte[] data, int dataLength, int flags) { 074 CANAPIJNI.writeCANPacket(m_handle, apiId, data, dataLength, flags); 075 } 076 077 /** 078 * Write a repeating packet to the CAN device with a specific ID. This ID is 10 bits. The RoboRIO 079 * will automatically repeat the packet at the specified interval 080 * 081 * @param apiId The API ID to write. 082 * @param data The data to write 083 * @param dataLength The data length 084 * @param flags The flags 085 * @param repeatMs The period to repeat the packet at. 086 */ 087 public void writePacketRepeating( 088 int apiId, byte[] data, int dataLength, int flags, int repeatMs) { 089 CANAPIJNI.writeCANPacketRepeating(m_handle, apiId, data, dataLength, flags, repeatMs); 090 } 091 092 /** 093 * Write an RTR frame to the CAN device with a specific ID. This ID is 10 bits. The length by spec 094 * must match what is returned by the responding device 095 * 096 * @param apiId The API ID to write. 097 * @param data The data to write 098 * @param dataLength The data length 099 * @param flags The flags 100 */ 101 public void writeRTRFrame(int apiId, byte[] data, int dataLength, int flags) { 102 CANAPIJNI.writeCANRTRFrame(m_handle, apiId, data, dataLength, flags); 103 } 104 105 /** 106 * Write a packet to the CAN device with a specific ID. This ID is 10 bits. 107 * 108 * @param apiId The API ID to write. 109 * @param data The data to write 110 * @param dataLength The data length 111 * @param flags The flags 112 * @return TODO 113 */ 114 public int writePacketNoThrow(int apiId, byte[] data, int dataLength, int flags) { 115 return CANAPIJNI.writeCANPacketNoThrow(m_handle, apiId, data, dataLength, flags); 116 } 117 118 /** 119 * Write a repeating packet to the CAN device with a specific ID. This ID is 10 bits. The RoboRIO 120 * will automatically repeat the packet at the specified interval 121 * 122 * @param apiId The API ID to write. 123 * @param data The data to write 124 * @param dataLength The data length 125 * @param flags The flags 126 * @param repeatMs The period to repeat the packet at. 127 * @return TODO 128 */ 129 public int writePacketRepeatingNoThrow( 130 int apiId, byte[] data, int dataLength, int flags, int repeatMs) { 131 return CANAPIJNI.writeCANPacketRepeatingNoThrow( 132 m_handle, apiId, data, dataLength, flags, repeatMs); 133 } 134 135 /** 136 * Write an RTR frame to the CAN device with a specific ID. This ID is 10 bits. The length by spec 137 * must match what is returned by the responding device 138 * 139 * @param apiId The API ID to write. 140 * @param data The data to write 141 * @param dataLength The data length 142 * @param flags The flags 143 * @return TODO 144 */ 145 public int writeRTRFrameNoThrow(int apiId, byte[] data, int dataLength, int flags) { 146 return CANAPIJNI.writeCANRTRFrameNoThrow(m_handle, apiId, data, dataLength, flags); 147 } 148 149 /** 150 * Stop a repeating packet with a specific ID. This ID is 10 bits. 151 * 152 * @param apiId The API ID to stop repeating 153 */ 154 public void stopPacketRepeating(int apiId) { 155 CANAPIJNI.stopCANPacketRepeating(m_handle, apiId); 156 } 157 158 /** 159 * Read a new CAN packet. This will only return properly once per packet received. Multiple calls 160 * without receiving another packet will return false. 161 * 162 * @param apiId The API ID to read. 163 * @param data Storage for the received data. 164 * @return True if the data is valid, otherwise false. 165 */ 166 public boolean readPacketNew(int apiId, CANReceiveMessage data) { 167 return CANAPIJNI.readCANPacketNew(m_handle, apiId, data); 168 } 169 170 /** 171 * Read a CAN packet. This will continuously return the last packet received, without accounting 172 * for packet age. 173 * 174 * @param apiId The API ID to read. 175 * @param data Storage for the received data. 176 * @return True if the data is valid, otherwise false. 177 */ 178 public boolean readPacketLatest(int apiId, CANReceiveMessage data) { 179 return CANAPIJNI.readCANPacketLatest(m_handle, apiId, data); 180 } 181 182 /** 183 * Read a CAN packet. This will return the last packet received until the packet is older than the 184 * requested timeout. Then it will return false. 185 * 186 * @param apiId The API ID to read. 187 * @param timeoutMs The timeout time for the packet 188 * @param data Storage for the received data. 189 * @return True if the data is valid, otherwise false. 190 */ 191 public boolean readPacketTimeout(int apiId, CANReceiveMessage data, int timeoutMs) { 192 return CANAPIJNI.readCANPacketTimeout(m_handle, apiId, data, timeoutMs); 193 } 194}