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.CANData; 009import edu.wpi.first.hal.FRCNetComm.tResourceType; 010import edu.wpi.first.hal.HAL; 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 public static final int kTeamManufacturer = 8; 025 public static final int kTeamDeviceType = 10; 026 027 private final int m_handle; 028 029 /** 030 * Create a new CAN communication interface with the specific device ID. This uses the team 031 * manufacturer and device types. The device ID is 6 bits (0-63). 032 * 033 * @param deviceId The device id 034 */ 035 public CAN(int deviceId) { 036 m_handle = CANAPIJNI.initializeCAN(kTeamManufacturer, deviceId, kTeamDeviceType); 037 HAL.report(tResourceType.kResourceType_CAN, deviceId + 1); 038 } 039 040 /** 041 * Create a new CAN communication interface with a specific device ID, manufacturer and device 042 * type. The device ID is 6 bits, the manufacturer is 8 bits, and the device type is 5 bits. 043 * 044 * @param deviceId The device ID 045 * @param deviceManufacturer The device manufacturer 046 * @param deviceType The device type 047 */ 048 public CAN(int deviceId, int deviceManufacturer, int deviceType) { 049 m_handle = CANAPIJNI.initializeCAN(deviceManufacturer, deviceId, deviceType); 050 HAL.report(tResourceType.kResourceType_CAN, deviceId + 1); 051 } 052 053 /** Closes the CAN communication. */ 054 @Override 055 public void close() { 056 if (m_handle != 0) { 057 CANAPIJNI.cleanCAN(m_handle); 058 } 059 } 060 061 /** 062 * Write a packet to the CAN device with a specific ID. This ID is 10 bits. 063 * 064 * @param data The data to write (8 bytes max) 065 * @param apiId The API ID to write. 066 */ 067 public void writePacket(byte[] data, int apiId) { 068 CANAPIJNI.writeCANPacket(m_handle, data, apiId); 069 } 070 071 /** 072 * Write a repeating packet to the CAN device with a specific ID. This ID is 10 bits. The RoboRIO 073 * will automatically repeat the packet at the specified interval 074 * 075 * @param data The data to write (8 bytes max) 076 * @param apiId The API ID to write. 077 * @param repeatMs The period to repeat the packet at. 078 */ 079 public void writePacketRepeating(byte[] data, int apiId, int repeatMs) { 080 CANAPIJNI.writeCANPacketRepeating(m_handle, data, apiId, repeatMs); 081 } 082 083 /** 084 * Write an RTR frame to the CAN device with a specific ID. This ID is 10 bits. The length by spec 085 * must match what is returned by the responding device 086 * 087 * @param length The length to request (0 to 8) 088 * @param apiId The API ID to write. 089 */ 090 public void writeRTRFrame(int length, int apiId) { 091 CANAPIJNI.writeCANRTRFrame(m_handle, length, apiId); 092 } 093 094 /** 095 * Write a packet to the CAN device with a specific ID. This ID is 10 bits. 096 * 097 * @param data The data to write (8 bytes max) 098 * @param apiId The API ID to write. 099 * @return TODO 100 */ 101 public int writePacketNoThrow(byte[] data, int apiId) { 102 return CANAPIJNI.writeCANPacketNoThrow(m_handle, data, apiId); 103 } 104 105 /** 106 * Write a repeating packet to the CAN device with a specific ID. This ID is 10 bits. The RoboRIO 107 * will automatically repeat the packet at the specified interval 108 * 109 * @param data The data to write (8 bytes max) 110 * @param apiId The API ID to write. 111 * @param repeatMs The period to repeat the packet at. 112 * @return TODO 113 */ 114 public int writePacketRepeatingNoThrow(byte[] data, int apiId, int repeatMs) { 115 return CANAPIJNI.writeCANPacketRepeatingNoThrow(m_handle, data, apiId, repeatMs); 116 } 117 118 /** 119 * Write an RTR frame to the CAN device with a specific ID. This ID is 10 bits. The length by spec 120 * must match what is returned by the responding device 121 * 122 * @param length The length to request (0 to 8) 123 * @param apiId The API ID to write. 124 * @return TODO 125 */ 126 public int writeRTRFrameNoThrow(int length, int apiId) { 127 return CANAPIJNI.writeCANRTRFrameNoThrow(m_handle, length, apiId); 128 } 129 130 /** 131 * Stop a repeating packet with a specific ID. This ID is 10 bits. 132 * 133 * @param apiId The API ID to stop repeating 134 */ 135 public void stopPacketRepeating(int apiId) { 136 CANAPIJNI.stopCANPacketRepeating(m_handle, apiId); 137 } 138 139 /** 140 * Read a new CAN packet. This will only return properly once per packet received. Multiple calls 141 * without receiving another packet will return false. 142 * 143 * @param apiId The API ID to read. 144 * @param data Storage for the received data. 145 * @return True if the data is valid, otherwise false. 146 */ 147 public boolean readPacketNew(int apiId, CANData data) { 148 return CANAPIJNI.readCANPacketNew(m_handle, apiId, data); 149 } 150 151 /** 152 * Read a CAN packet. This will continuously return the last packet received, without accounting 153 * for packet age. 154 * 155 * @param apiId The API ID to read. 156 * @param data Storage for the received data. 157 * @return True if the data is valid, otherwise false. 158 */ 159 public boolean readPacketLatest(int apiId, CANData data) { 160 return CANAPIJNI.readCANPacketLatest(m_handle, apiId, data); 161 } 162 163 /** 164 * Read a CAN packet. This will return the last packet received until the packet is older than the 165 * requested timeout. Then it will return false. 166 * 167 * @param apiId The API ID to read. 168 * @param timeoutMs The timeout time for the packet 169 * @param data Storage for the received data. 170 * @return True if the data is valid, otherwise false. 171 */ 172 public boolean readPacketTimeout(int apiId, int timeoutMs, CANData data) { 173 return CANAPIJNI.readCANPacketTimeout(m_handle, apiId, timeoutMs, data); 174 } 175 176 /** 177 * Reads the current value of the millisecond-resolution timer that {@link CANData} timestamps are 178 * based on. 179 * 180 * @return Current value of timer used as a base time for {@link CANData} timestamps in 181 * milliseconds 182 */ 183 public static long getTimestampBaseTime() { 184 return CANAPIJNI.getCANPacketBaseTime(); 185 } 186}