001 /*----------------------------------------------------------------------------*/
002 /* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
003 /* Open Source Software - may be modified and shared by FRC teams. The code */
004 /* must be accompanied by the FIRST BSD license file in the root directory of */
005 /* the project. */
006 /*----------------------------------------------------------------------------*/
007
008 package edu.wpi.first.wpilibj.can;
009
010 import com.sun.cldc.jna.*;
011 import com.sun.cldc.jna.ptr.IntByReference;
012 import edu.wpi.first.wpilibj.communication.Semaphore;
013
014 public class JaguarCANDriver {
015
016 public static final int kMaxMessageDataSize = 8;
017 private static final TaskExecutor taskExecutor = new TaskExecutor("FRC CANJaguar Task executor");
018
019 // void FRC_NetworkCommunication_JaguarCANDriver_sendMessage(UINT32 messageID, const UINT8 *data, UINT8 dataSize, INT32 *status);
020 private static final Function sendMessageFn = NativeLibrary.getDefaultInstance().getFunction("FRC_NetworkCommunication_JaguarCANDriver_sendMessage");
021
022 /**
023 * Send a message on the CAN bus
024 * @param messageID CAN MessageID to send on the CAN
025 * @param data Data payload to send with the message
026 */
027 public static void sendMessage(int messageID, byte[] data, int dataSize) throws CANTimeoutException {
028 Pointer sendDataBufferPointer = new Pointer(kMaxMessageDataSize);
029 sendDataBufferPointer.setBytes(0, data, 0, dataSize);
030 IntByReference sendStatus = new IntByReference(0);
031 sendStatus.setValue(0);
032 sendMessageFn.call4(messageID, sendDataBufferPointer, dataSize, sendStatus.getPointer().address().toUWord().toPrimitive());
033 int statusValue = sendStatus.getValue();
034 sendStatus.free();
035 sendDataBufferPointer.free();
036 CANExceptionFactory.checkStatus(statusValue, messageID);
037 }
038
039 // void FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(UINT32 *messageID, UINT8 *data, UINT8 *dataSize, UINT32 timeoutMs, INT32 *status);
040 private static final BlockingFunction receiveMessageFn = NativeLibrary.getDefaultInstance().getBlockingFunction("FRC_NetworkCommunication_JaguarCANDriver_receiveMessage");
041 public int receivedMessageId;
042
043 static {
044 receiveMessageFn.setTaskExecutor(taskExecutor);
045 }
046
047 /**
048 * Wait for a message to be received from the CAN bus.
049 * @param messageID MessageID filter to specify what message ID to be expected.
050 * @param data Buffer for received data
051 * @param timeout Number of seconds to wait for the expected message
052 * @return Actual size of the valid bytes in data
053 */
054 public byte receiveMessage(int messageID, byte[] data, double timeout) throws CANTimeoutException {
055 byte dataSize = 0;
056 IntByReference recvStatus = new IntByReference(0);
057 recvStatus.setValue(0);
058 Pointer messageIdPtr = new Pointer(4);
059 messageIdPtr.setInt(0, messageID);
060 Pointer dataSizePtr = new Pointer(1);
061 dataSizePtr.setByte(0, (byte) 0);
062 Pointer recvDataBufferPointer = new Pointer(kMaxMessageDataSize);
063 receiveMessageFn.call5(messageIdPtr, recvDataBufferPointer, dataSizePtr, (int) (timeout * 1000.0), recvStatus.getPointer().address().toUWord().toPrimitive());
064 int statusValue = recvStatus.getValue();
065 if (statusValue >= 0) {
066 dataSize = dataSizePtr.getByte(0);
067 receivedMessageId = messageIdPtr.getInt(0);
068 recvDataBufferPointer.getBytes(0, data, 0, data.length < dataSize ? data.length : dataSize);
069 }
070 recvDataBufferPointer.free();
071 dataSizePtr.free();
072 messageIdPtr.free();
073 recvStatus.free();
074 CANExceptionFactory.checkStatus(statusValue, messageID);
075 return dataSize;
076 }
077
078 /**
079 * Call receiveMessage with a default timeout parameter of 100ms
080 * @param messageID MessageID filter to specify what message ID to be expected.
081 * @param data Buffer for received data
082 * @return Actual size of the valid bytes in data
083 */
084 public byte receiveMessage(int messageID, byte[] data) throws CANTimeoutException {
085 return receiveMessage(messageID, data, 0.01);
086 }
087
088 // INT32 FRC_NetworkCommunication_JaguarCANDriver_receiveMessageStart_sem(UINT32 messageID, UINT32 semaphoreID, UINT32 timeoutMs, INT32 *status);
089 private static final Function receiveMessageStart_semFn = NativeLibrary.getDefaultInstance().getFunction("FRC_NetworkCommunication_JaguarCANDriver_receiveMessageStart_sem");
090
091 /**
092 * Start waiting for a message to be received from the CAN bus.
093 * @param messageID MessageID filter to specify what message ID to be expected.
094 * @param sem Semaphore that indicates that the receive call has completed.
095 * @param timeout Number of seconds to wait for the expected message.
096 * @return Data available now... call complete
097 */
098 public boolean receiveMessageStart(int messageID, Semaphore sem, double timeout) throws CANTimeoutException {
099 int retVal = 0;
100 IntByReference recvStatus = new IntByReference(0);
101 recvStatus.setValue(0);
102 retVal = receiveMessageStart_semFn.call4(messageID, sem.getPointer(), (int) (timeout * 1000.0), recvStatus.getPointer().address().toUWord().toPrimitive());
103 int statusValue = recvStatus.getValue();
104 recvStatus.free();
105 CANExceptionFactory.checkStatus(statusValue, messageID);
106 return retVal != 0;
107 }
108
109 // void FRC_NetworkCommunication_JaguarCANDriver_receiveMessageComplete(UINT32 *messageID, UINT8 *data, UINT8 *dataSize, INT32 *status);
110 private static final Function receiveMessageCompleteFn = NativeLibrary.getDefaultInstance().getFunction("FRC_NetworkCommunication_JaguarCANDriver_receiveMessageComplete");
111
112 /**
113 * Get the result of waiting for a message to be received from the CAN bus.
114 * @param messageID MessageID filter to specify what message ID to be expected.
115 * @param data Buffer for received data
116 * @return Actual size of the valid bytes in data
117 */
118 public byte receiveMessageComplete(int messageID, byte[] data) throws CANTimeoutException {
119 byte dataSize = 0;
120 IntByReference recvStatus = new IntByReference(0);
121 recvStatus.setValue(0);
122 Pointer messageIdPtr = new Pointer(4);
123 messageIdPtr.setInt(0, messageID);
124 Pointer dataSizePtr = new Pointer(1);
125 dataSizePtr.setByte(0, (byte) 0);
126 Pointer recvDataBufferPointer = new Pointer(kMaxMessageDataSize);
127 receiveMessageCompleteFn.call4(messageIdPtr, recvDataBufferPointer, dataSizePtr, recvStatus.getPointer().address().toUWord().toPrimitive());
128 int statusValue = recvStatus.getValue();
129 if (statusValue >= 0) {
130 dataSize = dataSizePtr.getByte(0);
131 receivedMessageId = messageIdPtr.getInt(0);
132 recvDataBufferPointer.getBytes(0, data, 0, data.length < dataSize ? data.length : dataSize);
133 }
134 recvDataBufferPointer.free();
135 dataSizePtr.free();
136 messageIdPtr.free();
137 recvStatus.free();
138 CANExceptionFactory.checkStatus(statusValue, messageID);
139 return dataSize;
140 }
141 }