Files
allwpilib/hal/lib/Athena/ctre/CtreCanNode.cpp
James Kuszmaul 28a41e4ac2 Added support for CAN Talon SRX in C++ and Java.
Currently, the JNI bindings are generated by Swig and, unfortunately,
  the interface available through Java is lower-level than that for C++
  (ie, direct access to the ctre code through the JNI bindings, rather
   than an interface on top of that), but it does work.
See eclipse plugins for some short samples.
There are a couple of short unit tests as placeholders.
Still needs some cleaning up.

Change-Id: Iae2f74693ca6b80bf7d5aca0625c66aa6e0b7f85

Added quick samples for C++/Java CAN Talon stuff.

Change-Id: I3acb27d6fd5568d88931e0d678c09973d436735d
2014-11-26 11:55:37 -05:00

102 lines
2.9 KiB
C++

#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include "CtreCanNode.h"
#include "NetworkCommunication/CANSessionMux.h"
#include <string.h> // memset
#include <unistd.h> // usleep
static const UINT32 kFullMessageIDMask = 0x1fffffff;
CtreCanNode::CtreCanNode(UINT8 deviceNumber)
{
_deviceNumber = deviceNumber;
}
CtreCanNode::~CtreCanNode()
{
}
void CtreCanNode::RegisterRx(uint32_t arbId)
{
/* no need to do anything, we just use new API to poll last received message */
}
void CtreCanNode::RegisterTx(uint32_t arbId, uint32_t periodMs)
{
int32_t status = 0;
txJob_t job = {0};
job.arbId = arbId;
job.periodMs = periodMs;
_txJobs[arbId] = job;
FRC_NetworkCommunication_CANSessionMux_sendMessage( job.arbId,
job.toSend,
8,
job.periodMs,
&status);
}
timespec diff(const timespec & start, const timespec & end)
{
timespec temp;
if ((end.tv_nsec-start.tv_nsec)<0) {
temp.tv_sec = end.tv_sec-start.tv_sec-1;
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
} else {
temp.tv_sec = end.tv_sec-start.tv_sec;
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
}
return temp;
}
CTR_Code CtreCanNode::GetRx(uint32_t arbId,uint8_t * dataBytes, uint32_t timeoutMs)
{
CTR_Code retval = CTR_OKAY;
int32_t status = 0;
uint8_t len = 0;
uint32_t timeStamp;
/* cap timeout at 999ms */
if(timeoutMs > 999)
timeoutMs = 999;
FRC_NetworkCommunication_CANSessionMux_receiveMessage(&arbId,kFullMessageIDMask,dataBytes,&len,&timeStamp,&status);
if(status == 0){
/* fresh update */
rxEvent_t & r = _rxRxEvents[arbId]; /* lookup entry or make a default new one with all zeroes */
clock_gettime(2,&r.time); /* fill in time */
memcpy(r.bytes, dataBytes, 8); /* fill in databytes */
}else{
/* did not get the message */
rxRxEvents_t::iterator i = _rxRxEvents.find(arbId);
if(i == _rxRxEvents.end()){
/* we've never gotten this mesage */
retval = CTR_RxTimeout;
/* fill caller's buffer with zeros */
memset(dataBytes,0,8);
}else{
/* we've gotten this message before but not recently */
memcpy(dataBytes,i->second.bytes,8);
/* get the time now */
struct timespec temp;
clock_gettime(2,&temp); /* get now */
/* how long has it been? */
temp = diff(i->second.time,temp); /* temp = now - last */
if(temp.tv_sec > 0){
retval = CTR_RxTimeout;
}else if(temp.tv_nsec > ((int32_t)timeoutMs*1000*1000)){
retval = CTR_RxTimeout;
}else {
/* our last update was recent enough */
}
}
}
return retval;
}
void CtreCanNode::FlushTx(uint32_t arbId)
{
int32_t status = 0;
txJobs_t::iterator iter = _txJobs.find(arbId);
if(iter != _txJobs.end())
FRC_NetworkCommunication_CANSessionMux_sendMessage( iter->second.arbId,
iter->second.toSend,
8,
iter->second.periodMs,
&status);
}