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    }