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 }