New netcomms .so and headers.

CAN isn't fully working yet, but this change is necessary to compile for the v9 image.

Change-Id: Ife99686a7e7a9979c95ec7a395d597011090fa37
This commit is contained in:
thomasclark
2014-06-16 10:24:48 -04:00
parent 58021f7397
commit 85dff7d2ec
19 changed files with 576 additions and 570 deletions

View File

@@ -6,11 +6,11 @@ if [ $(which sshpass) ]
then then
sshpass -p "" ssh admin@10.1.90.2 killall FRCUserProgram sshpass -p "" ssh admin@10.1.90.2 killall FRCUserProgram
sshpass -p "" scp target/cmake/wpilibc/wpilibC++IntegrationTests/FRCUserProgram admin@10.1.90.2:/home/admin sshpass -p "" scp target/cmake/wpilibc/wpilibC++IntegrationTests/FRCUserProgram admin@10.1.90.2:/home/admin
sshpass -p "" ssh admin@10.1.90.2 ./FRCUserProgram sshpass -p "" ssh admin@10.1.90.2 ./FRCUserProgram $*
else else
ssh admin@10.1.90.2 killall FRCUserProgram ssh admin@10.1.90.2 killall FRCUserProgram
scp target/cmake/wpilibc/wpilibC++IntegrationTests/FRCUserProgram admin@10.1.90.2:/home/admin scp target/cmake/wpilibc/wpilibC++IntegrationTests/FRCUserProgram admin@10.1.90.2:/home/admin
ssh admin@10.1.90.2 ./FRCUserProgram ssh admin@10.1.90.2 ./FRCUserProgram $*
fi fi

View File

@@ -11,7 +11,9 @@
#include <stdint.h> #include <stdint.h>
#define CAN_IS_FRAME_REMOTE 0x80000000 #define CAN_IS_FRAME_REMOTE 0x80000000
#define CAN_MESSAGE_ID_MASK 0x1FFFFFFF #define CAN_IS_FRAME_11BIT 0x40000000
#define CAN_29BIT_MESSAGE_ID_MASK 0x1FFFFFFF
#define CAN_11BIT_MESSAGE_ID_MASK 0x000007FF
class CANInterfacePlugin class CANInterfacePlugin
{ {
@@ -56,6 +58,6 @@ public:
* @param interface A pointer to an object that inherits from CANInterfacePlugin and implements * @param interface A pointer to an object that inherits from CANInterfacePlugin and implements
* the pure virtual interface. If NULL, unregister the current plugin. * the pure virtual interface. If NULL, unregister the current plugin.
*/ */
void FRC_NetworkCommunication_JaguarCANDriver_registerInterface(CANInterfacePlugin* interface); void FRC_NetworkCommunication_CANSessionMux_registerInterface(CANInterfacePlugin* interface);
#endif // __CANInterfacePlugin_h__ #endif // __CANInterfacePlugin_h__

View File

@@ -0,0 +1,61 @@
// CANSessionMux.h
//
// Defines the API for building a CAN Interface Plugin to support
// PWM-cable-free CAN motor control on FRC robots. This allows you
// to connect any CAN interface to the secure Jaguar CAN driver.
//
#ifndef __CANSessionMux_h__
#define __CANSessionMux_h__
#if defined(__vxworks)
#include <vxWorks.h>
#else
#include <stdint.h>
#endif
#define CAN_SEND_PERIOD_NO_REPEAT 0
#define CAN_SEND_PERIOD_STOP_REPEATING -1
/* Flags in the upper bits of the messageID */
#define CAN_IS_FRAME_REMOTE 0x80000000
#define CAN_IS_FRAME_11BIT 0x40000000
#define ERR_CANSessionMux_InvalidBuffer -44086
#define ERR_CANSessionMux_MessageNotFound -44087
#define WARN_CANSessionMux_NoToken 44087
#define ERR_CANSessionMux_NotAllowed -44088
#define ERR_CANSessionMux_NotInitialized -44089
struct tCANStreamMessage{
uint32_t messageID;
uint32_t timeStamp;
uint8_t data[8];
uint8_t dataSize;
};
namespace nCANSessionMux
{
void sendMessage_wrapper(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t periodMs, int32_t *status);
void receiveMessage_wrapper(uint32_t *messageID, uint32_t messageIDMask, uint8_t *data, uint8_t *dataSize, uint32_t *timeStamp, int32_t *status);
void openStreamSession(uint32_t *sessionHandle, uint32_t messageID, uint32_t messageIDMask, uint32_t maxMessages, int32_t *status);
void closeStreamSession(uint32_t sessionHandle);
void readStreamSession(uint32_t sessionHandle, struct tCANStreamMessage *messages, uint32_t messagesToRead, uint32_t *messagesRead, int32_t *status);
}
#ifdef __cplusplus
extern "C"
{
#endif
void FRC_NetworkCommunication_CANSessionMux_sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t periodMs, int32_t *status);
void FRC_NetworkCommunication_CANSessionMux_receiveMessage(uint32_t *messageID, uint32_t messageIDMask, uint8_t *data, uint8_t *dataSize, uint32_t *timeStamp, int32_t *status);
void FRC_NetworkCommunication_CANSessionMux_openStreamSession(uint32_t *sessionHandle, uint32_t messageID, uint32_t messageIDMask, uint32_t maxMessages, int32_t *status);
void FRC_NetworkCommunication_CANSessionMux_closeStreamSession(uint32_t sessionHandle);
void FRC_NetworkCommunication_CANSessionMux_readStreamSession(uint32_t sessionHandle, struct tCANStreamMessage *messages, uint32_t messagesToRead, uint32_t *messagesRead, int32_t *status);
#ifdef __cplusplus
}
#endif
#endif // __CANSessionMux_h__

View File

@@ -1,56 +0,0 @@
// JaguarCANDriver.h
//
// Defines the API for building a CAN Interface Plugin to support
// PWM-cable-free CAN motor control on FRC robots. This allows you
// to connect any CAN interface to the secure Jaguar CAN driver.
//
#ifndef __JaguarCANDriver_h__
#define __JaguarCANDriver_h__
#if defined(__vxworks)
#include <vxWorks.h>
#else
#include <stdint.h>
#include <pthread.h>
#endif
#ifdef USE_THRIFT
#include "NetCommRPCComm.h"
#include <vector>
#endif
namespace nJaguarCANDriver
{
void sendMessage_wrapper(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t *status);
void receiveMessage_wrapper(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, uint32_t timeoutMs, int32_t *status);
int32_t receiveMessageStart_wrapper(uint32_t messageID, uint32_t occurRefNum, uint32_t timeoutMs, int32_t *status);
#if defined (__vxworks)
int32_t receiveMessageStart_sem_wrapper(uint32_t messageID, uint32_t semaphoreID, uint32_t timeoutMs, int32_t *status);
#else
int32_t receiveMessageStart_mutex_wrapper(uint32_t messageID, pthread_mutex_t *mutex, uint32_t timeoutMs, int32_t *status);
#endif
void receiveMessageComplete_wrapper(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, int32_t *status);
#ifdef USE_THRIFT
void checkEvent_CAN(std::vector< CANEvent >& events);
#endif
}
#ifdef __cplusplus
extern "C"
{
#endif
void FRC_NetworkCommunication_JaguarCANDriver_sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t *status);
void FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, uint32_t timeoutMs, int32_t *status);
int32_t FRC_NetworkCommunication_JaguarCANDriver_receiveMessageStart(uint32_t messageID, uint32_t occurRefNum, uint32_t timeoutMs, int32_t *status);
#if defined (__vxworks)
int32_t FRC_NetworkCommunication_JaguarCANDriver_receiveMessageStart_sem(uint32_t messageID, uint32_t semaphoreID, uint32_t timeoutMs, int32_t *status);
#else
int32_t FRC_NetworkCommunication_JaguarCANDriver_receiveMessageStart_mutex(uint32_t messageID, pthread_mutex_t *mutex, uint32_t timeoutMs, int32_t *status);
#endif
void FRC_NetworkCommunication_JaguarCANDriver_receiveMessageComplete(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, int32_t *status);
#ifdef __cplusplus
}
#endif
#endif // __JaguarCANDriver_h__

View File

@@ -55,6 +55,5 @@ bool getSolenoid(void* solenoid_port_pointer, int32_t *status) {
void setSolenoid(void* solenoid_port_pointer, bool value, int32_t *status) { void setSolenoid(void* solenoid_port_pointer, bool value, int32_t *status) {
solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer; solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
*status = port->module->SetSolenoid(port->pin, value); port->module->SetSolenoid(port->pin, value);
} }

View File

@@ -1,9 +1,17 @@
#pragma GCC diagnostic ignored "-Wmissing-field-initializers" #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include "PCM.h" #include "PCM.h"
#include "NetworkCommunication/JaguarCANDriver.h" #include "NetworkCommunication/CANSessionMux.h"
#include <string.h> // memset #include <string.h> // memset
#include <unistd.h> // usleep #include <unistd.h> // usleep
static const UINT32 kFullMessageIDMask = 0x1fffffff;
/* This can be a constant, as long as nobody needs to updatie solenoids within
1/50 of a second. */
static const INT32 kCANPeriod = 20;
/* PCM Constructor - Clears all vars, establishes default settings, starts PCM background process /* PCM Constructor - Clears all vars, establishes default settings, starts PCM background process
* *
* @Return - void * @Return - void
@@ -313,7 +321,8 @@ void PCM::ReadStatusFrame(void) {
PcmStatus_t frame = {0}; PcmStatus_t frame = {0};
UINT8 size = 0; UINT8 size = 0;
INT32 status = 0; INT32 status = 0;
FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(&PCM_settings.statusFrameID, (uint8_t *)&frame, &size, 0 , &status); UINT32 timeStamp = 0;
FRC_NetworkCommunication_CANSessionMux_receiveMessage(&PCM_settings.statusFrameID, kFullMessageIDMask, (uint8_t *)&frame, &size, &timeStamp, &status);
if (status == 0) { if (status == 0) {
_timeSinceLastRx = 0; _timeSinceLastRx = 0;
_PcmStatus = frame; _PcmStatus = frame;
@@ -326,7 +335,8 @@ void PCM::ReadStatusFaultFrame(void) {
PcmStatusFault_t frame= {0}; PcmStatusFault_t frame= {0};
UINT8 size = 0; UINT8 size = 0;
INT32 status = 0; INT32 status = 0;
FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(&PCM_settings.statusFaultFrameID, (uint8_t *)&frame, &size, 0, &status); UINT32 timeStamp = 0;
FRC_NetworkCommunication_CANSessionMux_receiveMessage(&PCM_settings.statusFaultFrameID, kFullMessageIDMask, (uint8_t *)&frame, &size, &timeStamp, &status);
if (status == 0) { if (status == 0) {
_timeSinceLastRx = 0; _timeSinceLastRx = 0;
_PcmStatusFault = frame; _PcmStatusFault = frame;
@@ -339,7 +349,8 @@ void PCM::ReadDebugFrame(void) {
PcmDebug_t frame= {0}; PcmDebug_t frame= {0};
UINT8 size = 0; UINT8 size = 0;
INT32 status = 0; INT32 status = 0;
FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(&PCM_settings.debugFrameID, (uint8_t *)&frame, &size, 0, &status); UINT32 timeStamp = 0;
FRC_NetworkCommunication_CANSessionMux_receiveMessage(&PCM_settings.debugFrameID, kFullMessageIDMask, (uint8_t *)&frame, &size, &timeStamp, &status);
if (status == 0) { if (status == 0) {
_timeSinceLastRx = 0; _timeSinceLastRx = 0;
_PcmDebug = frame; _PcmDebug = frame;
@@ -351,7 +362,7 @@ void * PCM::ThreadFunc()
{ {
while(_threadIsRunning){ while(_threadIsRunning){
int32_t status = 0; int32_t status = 0;
FRC_NetworkCommunication_JaguarCANDriver_sendMessage(PCM_settings.controlFrameID, (const uint8_t *)&_PcmControl, sizeof(_PcmControl), &status); FRC_NetworkCommunication_CANSessionMux_sendMessage(PCM_settings.controlFrameID, (const uint8_t *)&_PcmControl, sizeof(_PcmControl), kCANPeriod, &status);
if(status == 0){ if(status == 0){
/* success */ /* success */
_timeSinceLastTx = 0; _timeSinceLastTx = 0;
@@ -473,4 +484,3 @@ extern "C" {
return retval; return retval;
} }
} }

View File

@@ -1,7 +1,7 @@
#ifndef PCM_H_ #ifndef PCM_H_
#define PCM_H_ #define PCM_H_
#include "ctre.h" //BIT Defines + Typedefs #include "ctre.h" //BIT Defines + Typedefs
#include <NetworkCommunication/JaguarCANDriver.h> //CAN Comm #include <NetworkCommunication/CANSessionMux.h> //CAN Comm
#include <pthread.h> #include <pthread.h>
/* encoder/decoders */ /* encoder/decoders */
typedef struct _PcmStatus_t{ typedef struct _PcmStatus_t{

View File

@@ -1,7 +1,10 @@
#include "PDP.h" #include "PDP.h"
#include "NetworkCommunication/JaguarCANDriver.h" #include "NetworkCommunication/CANSessionMux.h" //CAN Comm
#include <string.h> // memset #include <string.h> // memset
#include <unistd.h> // usleep #include <unistd.h> // usleep
#define kFullMessageIDMask 0x1fffffff
PDP::PDP(UINT8 deviceNumber) PDP::PDP(UINT8 deviceNumber)
{ {
memset(&_status1, 0, sizeof(_status1)); memset(&_status1, 0, sizeof(_status1));
@@ -107,7 +110,9 @@ uint64_t PDP::ReadCurrents(uint8_t api)
uint64_t frame = 0; uint64_t frame = 0;
UINT8 size = 0; UINT8 size = 0;
INT32 status = 0; INT32 status = 0;
FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(&PDP_Settings.frameIDs[api], (uint8_t *)&frame, &size, 0 , &status); UINT32 timeStamp = 0;
FRC_NetworkCommunication_CANSessionMux_receiveMessage(&PDP_Settings.frameIDs[api], kFullMessageIDMask, (uint8_t *)&frame, &size, &timeStamp, &status);
if (status == 0) { if (status == 0) {
_timeSinceLastRx = 0; _timeSinceLastRx = 0;
} else { } else {

View File

@@ -1,7 +1,7 @@
#ifndef PDP_H_ #ifndef PDP_H_
#define PDP_H_ #define PDP_H_
#include "ctre.h" //BIT Defines + Typedefs #include "ctre.h" //BIT Defines + Typedefs
#include <NetworkCommunication/JaguarCANDriver.h> //CAN Comm #include <NetworkCommunication/CANSessionMux.h> //CAN Comm
#include <pthread.h> #include <pthread.h>
/* encoder/decoders */ /* encoder/decoders */
typedef struct _PdpStatus1_t{ typedef struct _PdpStatus1_t{

View File

@@ -1,56 +0,0 @@
// JaguarCANDriver.h
//
// Defines the API for building a CAN Interface Plugin to support
// PWM-cable-free CAN motor control on FRC robots. This allows you
// to connect any CAN interface to the secure Jaguar CAN driver.
//
#ifndef __JaguarCANDriver_h__
#define __JaguarCANDriver_h__
#if defined(__vxworks)
#include <vxWorks.h>
#else
#include <stdint.h>
#include <pthread.h>
#endif
#ifdef USE_THRIFT
#include "NetCommRPCComm.h"
#include <vector>
#endif
namespace nJaguarCANDriver
{
void sendMessage_wrapper(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t *status);
void receiveMessage_wrapper(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, uint32_t timeoutMs, int32_t *status);
int32_t receiveMessageStart_wrapper(uint32_t messageID, uint32_t occurRefNum, uint32_t timeoutMs, int32_t *status);
#if defined (__vxworks)
int32_t receiveMessageStart_sem_wrapper(uint32_t messageID, uint32_t semaphoreID, uint32_t timeoutMs, int32_t *status);
#else
int32_t receiveMessageStart_mutex_wrapper(uint32_t messageID, pthread_mutex_t *mutex, uint32_t timeoutMs, int32_t *status);
#endif
void receiveMessageComplete_wrapper(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, int32_t *status);
#ifdef USE_THRIFT
void checkEvent_CAN(std::vector< CANEvent >& events);
#endif
}
#ifdef __cplusplus
extern "C"
{
#endif
void FRC_NetworkCommunication_JaguarCANDriver_sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t *status);
void FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, uint32_t timeoutMs, int32_t *status);
int32_t FRC_NetworkCommunication_JaguarCANDriver_receiveMessageStart(uint32_t messageID, uint32_t occurRefNum, uint32_t timeoutMs, int32_t *status);
#if defined (__vxworks)
int32_t FRC_NetworkCommunication_JaguarCANDriver_receiveMessageStart_sem(uint32_t messageID, uint32_t semaphoreID, uint32_t timeoutMs, int32_t *status);
#else
int32_t FRC_NetworkCommunication_JaguarCANDriver_receiveMessageStart_mutex(uint32_t messageID, pthread_mutex_t *mutex, uint32_t timeoutMs, int32_t *status);
#endif
void FRC_NetworkCommunication_JaguarCANDriver_receiveMessageComplete(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, int32_t *status);
#ifdef __cplusplus
}
#endif
#endif // __JaguarCANDriver_h__

View File

@@ -15,6 +15,8 @@
#include "LiveWindow/LiveWindowSendable.h" #include "LiveWindow/LiveWindowSendable.h"
#include "tables/ITable.h" #include "tables/ITable.h"
#include <utility>
/** /**
* Luminary Micro Jaguar Speed Control * Luminary Micro Jaguar Speed Control
*/ */
@@ -43,7 +45,6 @@ public:
// SpeedController interface // SpeedController interface
virtual float Get(); virtual float Get();
virtual void Set(float value, uint8_t syncGroup=0); virtual void Set(float value, uint8_t syncGroup=0);
void SetNoAck(float value, uint8_t syncGroup=0);
virtual void Disable(); virtual void Disable();
// PIDOutput interface // PIDOutput interface
@@ -71,7 +72,6 @@ public:
bool GetForwardLimitOK(); bool GetForwardLimitOK();
bool GetReverseLimitOK(); bool GetReverseLimitOK();
uint16_t GetFaults(); uint16_t GetFaults();
bool GetPowerCycled();
void SetVoltageRampRate(double rampRate); void SetVoltageRampRate(double rampRate);
virtual uint32_t GetFirmwareVersion(); virtual uint32_t GetFirmwareVersion();
uint8_t GetHardwareVersion(); uint8_t GetHardwareVersion();
@@ -105,18 +105,52 @@ protected:
int16_t unpackint16_t(uint8_t *buffer); int16_t unpackint16_t(uint8_t *buffer);
int32_t unpackint32_t(uint8_t *buffer); int32_t unpackint32_t(uint8_t *buffer);
virtual void setTransaction(uint32_t messageID, const uint8_t *data, uint8_t dataSize); virtual void setTransaction(uint32_t messageID, const uint8_t *data, uint8_t dataSize);
virtual void getTransaction(uint32_t messageID, uint8_t *data, uint8_t *dataSize); virtual bool getTransaction(uint32_t messageID, uint8_t *data, uint8_t *dataSize);
static int32_t sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize); static int32_t sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize);
//#define kTimeoutCan 0.02 static int32_t receiveMessage(uint32_t *messageID, uint8_t *data, uint8_t *dataSize);
#define kTimeoutCan 0.0
static int32_t receiveMessage(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, float timeout = kTimeoutCan);
uint8_t m_deviceNumber; uint8_t m_deviceNumber;
ControlMode m_controlMode; ControlMode m_controlMode;
MUTEX_ID m_transactionSemaphore; MUTEX_ID m_transactionSemaphore;
double m_maxOutputVoltage; double m_maxOutputVoltage;
enum CANValue {
CAN_VALUE = 0x1,
CAN_SPEED_REFERENCE = 0x2,
CAN_POSITION_REFERENCE = 0x4,
CAN_P = 0x8, CAN_I = 0x10, CAN_D = 0x20,
CAN_BUS_VOLTAGE = 0x40,
CAN_OUTPUT_VOLTAGE = 0x80,
CAN_OUTPUT_CURRENT = 0x100,
CAN_TEMPERATURE = 0x200,
CAN_POSITION = 0x400,
CAN_SPEED = 0x800,
CAN_LIMITS = 0x1000,
CAN_FAULTS = 0x2000,
CAN_FIRMWARE_VERSION = 0x4000,
CAN_HARDWARE_VERSION = 0x8000,
CAN_EVERYTHING = 0xffff
};
bool isUnverified(CANValue value) const;
void verifyCANValues();
// Keep track of what cached CAN values have been verified.
CANValue m_verified_values;
// Cached CAN data
float m_value;
SpeedReference m_speedReference;
PositionReference m_positionReference;
double m_p, m_i, m_d;
float m_busVoltage, m_outputVoltage, m_outputCurrent, m_temperature;
double m_position, m_speed;
uint8_t m_limits;
uint16_t m_faults;
uint32_t m_firmwareVersion;
uint8_t m_hardwareVersion;
MotorSafetyHelper *m_safetyHelper; MotorSafetyHelper *m_safetyHelper;
void ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew); void ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew);

View File

@@ -11,7 +11,9 @@
#include <stdint.h> #include <stdint.h>
#define CAN_IS_FRAME_REMOTE 0x80000000 #define CAN_IS_FRAME_REMOTE 0x80000000
#define CAN_MESSAGE_ID_MASK 0x1FFFFFFF #define CAN_IS_FRAME_11BIT 0x40000000
#define CAN_29BIT_MESSAGE_ID_MASK 0x1FFFFFFF
#define CAN_11BIT_MESSAGE_ID_MASK 0x000007FF
class CANInterfacePlugin class CANInterfacePlugin
{ {
@@ -56,6 +58,6 @@ public:
* @param interface A pointer to an object that inherits from CANInterfacePlugin and implements * @param interface A pointer to an object that inherits from CANInterfacePlugin and implements
* the pure virtual interface. If NULL, unregister the current plugin. * the pure virtual interface. If NULL, unregister the current plugin.
*/ */
void FRC_NetworkCommunication_JaguarCANDriver_registerInterface(CANInterfacePlugin* interface); void FRC_NetworkCommunication_CANSessionMux_registerInterface(CANInterfacePlugin* interface);
#endif // __CANInterfacePlugin_h__ #endif // __CANInterfacePlugin_h__

View File

@@ -0,0 +1,61 @@
// CANSessionMux.h
//
// Defines the API for building a CAN Interface Plugin to support
// PWM-cable-free CAN motor control on FRC robots. This allows you
// to connect any CAN interface to the secure Jaguar CAN driver.
//
#ifndef __CANSessionMux_h__
#define __CANSessionMux_h__
#if defined(__vxworks)
#include <vxWorks.h>
#else
#include <stdint.h>
#endif
#define CAN_SEND_PERIOD_NO_REPEAT 0
#define CAN_SEND_PERIOD_STOP_REPEATING -1
/* Flags in the upper bits of the messageID */
#define CAN_IS_FRAME_REMOTE 0x80000000
#define CAN_IS_FRAME_11BIT 0x40000000
#define ERR_CANSessionMux_InvalidBuffer -44086
#define ERR_CANSessionMux_MessageNotFound -44087
#define WARN_CANSessionMux_NoToken 44087
#define ERR_CANSessionMux_NotAllowed -44088
#define ERR_CANSessionMux_NotInitialized -44089
struct tCANStreamMessage{
uint32_t messageID;
uint32_t timeStamp;
uint8_t data[8];
uint8_t dataSize;
};
namespace nCANSessionMux
{
void sendMessage_wrapper(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t periodMs, int32_t *status);
void receiveMessage_wrapper(uint32_t *messageID, uint32_t messageIDMask, uint8_t *data, uint8_t *dataSize, uint32_t *timeStamp, int32_t *status);
void openStreamSession(uint32_t *sessionHandle, uint32_t messageID, uint32_t messageIDMask, uint32_t maxMessages, int32_t *status);
void closeStreamSession(uint32_t sessionHandle);
void readStreamSession(uint32_t sessionHandle, struct tCANStreamMessage *messages, uint32_t messagesToRead, uint32_t *messagesRead, int32_t *status);
}
#ifdef __cplusplus
extern "C"
{
#endif
void FRC_NetworkCommunication_CANSessionMux_sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t periodMs, int32_t *status);
void FRC_NetworkCommunication_CANSessionMux_receiveMessage(uint32_t *messageID, uint32_t messageIDMask, uint8_t *data, uint8_t *dataSize, uint32_t *timeStamp, int32_t *status);
void FRC_NetworkCommunication_CANSessionMux_openStreamSession(uint32_t *sessionHandle, uint32_t messageID, uint32_t messageIDMask, uint32_t maxMessages, int32_t *status);
void FRC_NetworkCommunication_CANSessionMux_closeStreamSession(uint32_t sessionHandle);
void FRC_NetworkCommunication_CANSessionMux_readStreamSession(uint32_t sessionHandle, struct tCANStreamMessage *messages, uint32_t messagesToRead, uint32_t *messagesRead, int32_t *status);
#ifdef __cplusplus
}
#endif
#endif // __CANSessionMux_h__

View File

@@ -1,56 +0,0 @@
// JaguarCANDriver.h
//
// Defines the API for building a CAN Interface Plugin to support
// PWM-cable-free CAN motor control on FRC robots. This allows you
// to connect any CAN interface to the secure Jaguar CAN driver.
//
#ifndef __JaguarCANDriver_h__
#define __JaguarCANDriver_h__
#if defined(__vxworks)
#include <vxWorks.h>
#else
#include <stdint.h>
#include <pthread.h>
#endif
#ifdef USE_THRIFT
#include "NetCommRPCComm.h"
#include <vector>
#endif
namespace nJaguarCANDriver
{
void sendMessage_wrapper(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t *status);
void receiveMessage_wrapper(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, uint32_t timeoutMs, int32_t *status);
int32_t receiveMessageStart_wrapper(uint32_t messageID, uint32_t occurRefNum, uint32_t timeoutMs, int32_t *status);
#if defined (__vxworks)
int32_t receiveMessageStart_sem_wrapper(uint32_t messageID, uint32_t semaphoreID, uint32_t timeoutMs, int32_t *status);
#else
int32_t receiveMessageStart_mutex_wrapper(uint32_t messageID, pthread_mutex_t *mutex, uint32_t timeoutMs, int32_t *status);
#endif
void receiveMessageComplete_wrapper(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, int32_t *status);
#ifdef USE_THRIFT
void checkEvent_CAN(std::vector< CANEvent >& events);
#endif
}
#ifdef __cplusplus
extern "C"
{
#endif
void FRC_NetworkCommunication_JaguarCANDriver_sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t *status);
void FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, uint32_t timeoutMs, int32_t *status);
int32_t FRC_NetworkCommunication_JaguarCANDriver_receiveMessageStart(uint32_t messageID, uint32_t occurRefNum, uint32_t timeoutMs, int32_t *status);
#if defined (__vxworks)
int32_t FRC_NetworkCommunication_JaguarCANDriver_receiveMessageStart_sem(uint32_t messageID, uint32_t semaphoreID, uint32_t timeoutMs, int32_t *status);
#else
int32_t FRC_NetworkCommunication_JaguarCANDriver_receiveMessageStart_mutex(uint32_t messageID, pthread_mutex_t *mutex, uint32_t timeoutMs, int32_t *status);
#endif
void FRC_NetworkCommunication_JaguarCANDriver_receiveMessageComplete(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, int32_t *status);
#ifdef __cplusplus
}
#endif
#endif // __JaguarCANDriver_h__

View File

@@ -26,7 +26,7 @@ namespace nUsageReporting
kResourceType_CANPlugin, kResourceType_CANPlugin,
kResourceType_Accelerometer, kResourceType_Accelerometer,
kResourceType_ADXL345, kResourceType_ADXL345,
kResourceType_AnalogInput, kResourceType_AnalogChannel,
kResourceType_AnalogTrigger, kResourceType_AnalogTrigger,
kResourceType_AnalogTriggerOutput, kResourceType_AnalogTriggerOutput,
kResourceType_CANJaguar, kResourceType_CANJaguar,

View File

@@ -6,7 +6,7 @@
#include "CANJaguar.h" #include "CANJaguar.h"
#define tNIRIO_i32 int #define tNIRIO_i32 int
#include "CAN/JaguarCANDriver.h" #include "NetworkCommunication/CANSessionMux.h"
#include "CAN/can_proto.h" #include "CAN/can_proto.h"
//#include "NetworkCommunication/UsageReporting.h" //#include "NetworkCommunication/UsageReporting.h"
#include "WPIErrors.h" #include "WPIErrors.h"
@@ -23,19 +23,8 @@
const int32_t CANJaguar::kControllerRate; const int32_t CANJaguar::kControllerRate;
constexpr double CANJaguar::kApproxBusVoltage; constexpr double CANJaguar::kApproxBusVoltage;
// TODO: Make this a parameter
const int kDefaultCANPeriod = 20;
void _sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t *status)
{
FRC_NetworkCommunication_JaguarCANDriver_sendMessage(messageID,data,dataSize,status);
}
void _receiveMessage(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, uint32_t timeoutMs, int32_t *status)
{
FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(messageID,data,dataSize,timeoutMs,status);
}
/** /**
* Common initialization code called by all constructors. * Common initialization code called by all constructors.
@@ -54,7 +43,8 @@ void CANJaguar::InitCANJaguar()
uint32_t fwVer = GetFirmwareVersion(); uint32_t fwVer = GetFirmwareVersion();
if (StatusIsFatal()) if (StatusIsFatal())
return; return;
// 3330 was the first shipping RDK firmware version for the Jaguar
// 3330 was the first shipping RDK firmware version for the Jaguar
if (fwVer >= 3330 || fwVer < 101) if (fwVer >= 3330 || fwVer < 101)
{ {
char buf[256]; char buf[256];
@@ -69,6 +59,7 @@ void CANJaguar::InitCANJaguar()
wpi_setWPIErrorWithContext(JaguarVersionError, buf); wpi_setWPIErrorWithContext(JaguarVersionError, buf);
return; return;
} }
switch (m_controlMode) switch (m_controlMode)
{ {
case kPercentVbus: case kPercentVbus:
@@ -81,6 +72,26 @@ void CANJaguar::InitCANJaguar()
} }
m_safetyHelper = new MotorSafetyHelper(this); m_safetyHelper = new MotorSafetyHelper(this);
m_value = 0.0f;
m_speedReference = kSpeedRef_None;
m_positionReference = kPosRef_None;
m_p = 0.0;
m_i = 0.0;
m_d = 0.0;
m_busVoltage = 0.0f;
m_outputVoltage = 0.0f;
m_outputCurrent = 0.0f;
m_temperature = 0.0f;
m_position = 0.0;
m_speed = 0.0;
m_limits = 0x00;
m_faults = 0x0000;
m_firmwareVersion = 0;
m_hardwareVersion = 0;
m_verified_values = CAN_EVERYTHING;
HALReport(HALUsageReporting::kResourceType_CANJaguar, m_deviceNumber, m_controlMode); HALReport(HALUsageReporting::kResourceType_CANJaguar, m_deviceNumber, m_controlMode);
LiveWindow::GetInstance()->AddActuator("CANJaguar", m_deviceNumber, this); LiveWindow::GetInstance()->AddActuator("CANJaguar", m_deviceNumber, this);
} }
@@ -177,90 +188,6 @@ void CANJaguar::Set(float outputValue, uint8_t syncGroup)
setTransaction(messageID, dataBuffer, dataSize); setTransaction(messageID, dataBuffer, dataSize);
if (m_safetyHelper) m_safetyHelper->Feed(); if (m_safetyHelper) m_safetyHelper->Feed();
} }
void CANJaguar::SetNoAck(float outputValue, uint8_t syncGroup)
{
uint32_t messageID;
uint8_t dataBuffer[8];
uint8_t dataSize;
if (m_safetyHelper && !m_safetyHelper->IsAlive())
{
EnableControl();
}
switch(m_controlMode)
{
case kPercentVbus:
{
messageID = LM_API_VOLT_T_SET_NO_ACK; //LM_API_VOLT_T_SET;
if (outputValue > 1.0) outputValue = 1.0;
if (outputValue < -1.0) outputValue = -1.0;
dataSize = packPercentage(dataBuffer, outputValue);
}
break;
case kSpeed:
{
messageID = LM_API_SPD_T_SET;
dataSize = packFXP16_16(dataBuffer, outputValue);
}
break;
case kPosition:
{
messageID = LM_API_POS_T_SET;
dataSize = packFXP16_16(dataBuffer, outputValue);
}
break;
case kCurrent:
{
messageID = LM_API_ICTRL_T_SET;
dataSize = packFXP8_8(dataBuffer, outputValue);
}
break;
case kVoltage:
{
messageID = LM_API_VCOMP_T_SET_NO_ACK; // LM_API_VCOMP_T_SET;
dataSize = packFXP8_8(dataBuffer, outputValue);
}
break;
default:
return;
}
if (syncGroup != 0)
{
dataBuffer[dataSize] = syncGroup;
dataSize++;
}
{ //setTransaction(messageID, dataBuffer, dataSize);
//uint32_t ackMessageID = LM_API_ACK | m_deviceNumber;
int32_t localStatus = 0;
// If there was an error on this object and it wasn't a timeout, refuse to talk to the device
// Call ClearError() on the object to try again
//if (StatusIsFatal() && GetError().GetCode() != -44087)
// return;
// Make sure we don't have more than one transaction with the same Jaguar outstanding.
takeMutex(m_transactionSemaphore);
// Throw away any stale acks.
//receiveMessage(&ackMessageID, NULL, 0, 0.0f);
// Send the message with the data.
localStatus = sendMessage(messageID | m_deviceNumber, dataBuffer, dataSize);
wpi_setErrorWithContext(localStatus, "sendMessage");
// Wait for an ack.
//localStatus = receiveMessage(&ackMessageID, NULL, 0);
//wpi_setErrorWithContext(localStatus, "receiveMessage");
// Transaction complete.
giveMutex(m_transactionSemaphore);
}
if (m_safetyHelper) m_safetyHelper->Feed();
}
/** /**
* Get the recently set outputValue setpoint. * Get the recently set outputValue setpoint.
@@ -282,42 +209,37 @@ float CANJaguar::Get()
switch(m_controlMode) switch(m_controlMode)
{ {
case kPercentVbus: case kPercentVbus:
getTransaction(LM_API_VOLT_SET, dataBuffer, &dataSize); if(getTransaction(LM_API_VOLT_SET, dataBuffer, &dataSize)) {
if (dataSize == sizeof(int16_t)) m_value = unpackPercentage(dataBuffer);
{ }
return unpackPercentage(dataBuffer); break;
}
break;
case kSpeed: case kSpeed:
getTransaction(LM_API_SPD_SET, dataBuffer, &dataSize); if(getTransaction(LM_API_SPD_SET, dataBuffer, &dataSize)) {
if (dataSize == sizeof(int32_t)) m_value = unpackFXP16_16(dataBuffer);
{ }
return unpackFXP16_16(dataBuffer); break;
}
break;
case kPosition: case kPosition:
getTransaction(LM_API_POS_SET, dataBuffer, &dataSize); if(getTransaction(LM_API_POS_SET, dataBuffer, &dataSize)) {
if (dataSize == sizeof(int32_t)) m_value = unpackFXP16_16(dataBuffer);
{ }
return unpackFXP16_16(dataBuffer); break;
}
break;
case kCurrent: case kCurrent:
getTransaction(LM_API_ICTRL_SET, dataBuffer, &dataSize); if(getTransaction(LM_API_ICTRL_SET, dataBuffer, &dataSize)) {
if (dataSize == sizeof(int16_t)) m_value = unpackFXP8_8(dataBuffer);
{ }
return unpackFXP8_8(dataBuffer); break;
}
break;
case kVoltage: case kVoltage:
getTransaction(LM_API_VCOMP_SET, dataBuffer, &dataSize); if(getTransaction(LM_API_VCOMP_SET, dataBuffer, &dataSize)) {
if (dataSize == sizeof(int16_t)) m_value = unpackFXP8_8(dataBuffer);
{ }
return unpackFXP8_8(dataBuffer);
}
break; break;
} }
return 0.0;
return m_value;
} }
/** /**
@@ -428,7 +350,7 @@ int32_t CANJaguar::unpackint32_t(uint8_t *buffer)
*/ */
int32_t CANJaguar::sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize) int32_t CANJaguar::sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize)
{ {
static const uint32_t kTrustedMessages[] = { static const uint32_t kTrustedMessages[] = {
LM_API_VOLT_T_EN, LM_API_VOLT_T_SET, LM_API_SPD_T_EN, LM_API_SPD_T_SET, LM_API_VOLT_T_EN, LM_API_VOLT_T_SET, LM_API_SPD_T_EN, LM_API_SPD_T_SET,
LM_API_VCOMP_T_EN, LM_API_VCOMP_T_SET, LM_API_POS_T_EN, LM_API_POS_T_SET, LM_API_VCOMP_T_EN, LM_API_VCOMP_T_SET, LM_API_POS_T_EN, LM_API_POS_T_SET,
LM_API_ICTRL_T_EN, LM_API_ICTRL_T_SET}; LM_API_ICTRL_T_EN, LM_API_ICTRL_T_SET};
@@ -452,14 +374,16 @@ int32_t CANJaguar::sendMessage(uint32_t messageID, const uint8_t *data, uint8_t
{ {
dataBuffer[j + 2] = data[j]; dataBuffer[j + 2] = data[j];
} }
//TODO: put this back when CAN shows up
_sendMessage(messageID, dataBuffer, dataSize + 2, &status); FRC_NetworkCommunication_CANSessionMux_sendMessage(messageID, dataBuffer, dataSize + 2, kDefaultCANPeriod, &status);
return status; return status;
} }
} }
//TODO: put this back when CAN shows up
_sendMessage(messageID, data, dataSize, &status); FRC_NetworkCommunication_CANSessionMux_sendMessage(messageID, data, dataSize, kDefaultCANPeriod, &status);
return status;
return status;
} }
/** /**
@@ -468,15 +392,15 @@ int32_t CANJaguar::sendMessage(uint32_t messageID, const uint8_t *data, uint8_t
* @param messageID The messageID to read from the CAN bus * @param messageID The messageID to read from the CAN bus
* @param data The up to 8 bytes of data that was received with the message * @param data The up to 8 bytes of data that was received with the message
* @param dataSize Indicates how much data was received * @param dataSize Indicates how much data was received
* @param timeout Specify how long to wait for a message (in seconds)
* @return Status of receive call * @return Status of receive call
*/ */
int32_t CANJaguar::receiveMessage(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, float timeout) int32_t CANJaguar::receiveMessage(uint32_t *messageID, uint8_t *data, uint8_t *dataSize)
{ {
uint32_t timeStamp;
int32_t status = 0; int32_t status = 0;
//TODO: put this back when CAN shows up
_receiveMessage(messageID, data, dataSize, FRC_NetworkCommunication_CANSessionMux_receiveMessage(messageID, kFullMessageIDMask, data, dataSize, &timeStamp, &status);
(uint32_t)(timeout * 1000), &status);
return status; return status;
} }
@@ -492,7 +416,6 @@ int32_t CANJaguar::receiveMessage(uint32_t *messageID, uint8_t *data, uint8_t *d
*/ */
void CANJaguar::setTransaction(uint32_t messageID, const uint8_t *data, uint8_t dataSize) void CANJaguar::setTransaction(uint32_t messageID, const uint8_t *data, uint8_t dataSize)
{ {
uint32_t ackMessageID = LM_API_ACK | m_deviceNumber;
int32_t localStatus = 0; int32_t localStatus = 0;
// If there was an error on this object and it wasn't a timeout, refuse to talk to the device // If there was an error on this object and it wasn't a timeout, refuse to talk to the device
@@ -503,14 +426,9 @@ void CANJaguar::setTransaction(uint32_t messageID, const uint8_t *data, uint8_t
// Make sure we don't have more than one transaction with the same Jaguar outstanding. // Make sure we don't have more than one transaction with the same Jaguar outstanding.
takeMutex(m_transactionSemaphore); takeMutex(m_transactionSemaphore);
// Throw away any stale acks.
receiveMessage(&ackMessageID, NULL, 0, 0.0f);
// Send the message with the data. // Send the message with the data.
localStatus = sendMessage(messageID | m_deviceNumber, data, dataSize); localStatus = sendMessage(messageID | m_deviceNumber, data, dataSize);
wpi_setErrorWithContext(localStatus, "sendMessage"); wpi_setErrorWithContext(localStatus, "sendMessage");
// Wait for an ack.
localStatus = receiveMessage(&ackMessageID, NULL, 0);
wpi_setErrorWithContext(localStatus, "receiveMessage");
// Transaction complete. // Transaction complete.
giveMutex(m_transactionSemaphore); giveMutex(m_transactionSemaphore);
@@ -524,26 +442,29 @@ void CANJaguar::setTransaction(uint32_t messageID, const uint8_t *data, uint8_t
* @param messageID The messageID to read from the CAN bus (device number is added internally) * @param messageID The messageID to read from the CAN bus (device number is added internally)
* @param data The up to 8 bytes of data that was received with the message * @param data The up to 8 bytes of data that was received with the message
* @param dataSize Indicates how much data was received * @param dataSize Indicates how much data was received
*
* @return True if the message was found. Otherwise, no new message is available,
* so a cached value will be used.
*/ */
void CANJaguar::getTransaction(uint32_t messageID, uint8_t *data, uint8_t *dataSize) bool CANJaguar::getTransaction(uint32_t messageID, uint8_t *data, uint8_t *dataSize)
{ {
uint32_t targetedMessageID = messageID | m_deviceNumber; uint32_t targetedMessageID = messageID | m_deviceNumber;
int32_t localStatus = 0; int32_t localStatus = 0;
bool messageFound = true;
// If there was an error on this object and it wasn't a timeout, refuse to talk to the device // If there was an error on this object and it wasn't a message not found,
// Call ClearError() on the object to try again // refuse to talk to the device. Call ClearError() on the object to try again
if (StatusIsFatal() && GetError().GetCode() != -44087) if (StatusIsFatal() && GetError().GetCode() != ERR_CANSessionMux_MessageNotFound)
{ {
if (dataSize != NULL) if (dataSize != NULL)
*dataSize = 0; *dataSize = 0;
return; return false;
} }
// Make sure we don't have more than one transaction with the same Jaguar outstanding. // Make sure we don't have more than one transaction with the same Jaguar outstanding.
takeMutex(m_transactionSemaphore); takeMutex(m_transactionSemaphore);
// Throw away any stale responses.
receiveMessage(&targetedMessageID, NULL, 0, 0.0f);
// Send the message requesting data. // Send the message requesting data.
localStatus = sendMessage(targetedMessageID, NULL, 0); localStatus = sendMessage(targetedMessageID, NULL, 0);
wpi_setErrorWithContext(localStatus, "sendMessage"); wpi_setErrorWithContext(localStatus, "sendMessage");
@@ -551,10 +472,40 @@ void CANJaguar::getTransaction(uint32_t messageID, uint8_t *data, uint8_t *dataS
targetedMessageID &= 0x1FFFFFFF; targetedMessageID &= 0x1FFFFFFF;
// Wait for the data. // Wait for the data.
localStatus = receiveMessage(&targetedMessageID, data, dataSize); localStatus = receiveMessage(&targetedMessageID, data, dataSize);
wpi_setErrorWithContext(localStatus, "receiveMessage");
if(localStatus == ERR_CANSessionMux_MessageNotFound)
{
messageFound = false;
} else {
wpi_setErrorWithContext(localStatus, "receiveMessage");
}
// Transaction complete. // Transaction complete.
giveMutex(m_transactionSemaphore); giveMutex(m_transactionSemaphore);
return messageFound;
}
/**
* Check if a CAN value has been set but not verified yet.
*/
bool CANJaguar::isUnverified(CANValue value) const
{
return !(m_verified_values & value);
}
/**
* Check all unverified values and make sure they're equal to their local
* cached versions.
*
* If a value isn't available, it gets requested. If a value doesn't match up,
* it gets set again.
*/
void CANJaguar::verifyCANValues()
{
if(isUnverified(CAN_VALUE)) {
}
} }
/** /**
@@ -582,12 +533,12 @@ CANJaguar::SpeedReference CANJaguar::GetSpeedReference()
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
getTransaction(LM_API_SPD_REF, dataBuffer, &dataSize); if(getTransaction(LM_API_SPD_REF, dataBuffer, &dataSize))
if (dataSize == sizeof(uint8_t)) {
{ m_speedReference = (SpeedReference)*dataBuffer;
return (SpeedReference)*dataBuffer; }
}
return kSpeedRef_None; return m_speedReference;
} }
/** /**
@@ -616,12 +567,12 @@ CANJaguar::PositionReference CANJaguar::GetPositionReference()
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
getTransaction(LM_API_POS_REF, dataBuffer, &dataSize); if(getTransaction(LM_API_POS_REF, dataBuffer, &dataSize))
if (dataSize == sizeof(uint8_t))
{ {
return (PositionReference)*dataBuffer; m_positionReference = (PositionReference)*dataBuffer;
} }
return kPosRef_None;
return m_positionReference;
} }
/** /**
@@ -686,28 +637,26 @@ double CANJaguar::GetP()
wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode"); wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
break; break;
case kSpeed: case kSpeed:
getTransaction(LM_API_SPD_PC, dataBuffer, &dataSize); if(getTransaction(LM_API_SPD_PC, dataBuffer, &dataSize))
if (dataSize == sizeof(int32_t)) {
{ m_p = unpackFXP16_16(dataBuffer);
return unpackFXP16_16(dataBuffer); }
} break;
break;
case kPosition: case kPosition:
getTransaction(LM_API_POS_PC, dataBuffer, &dataSize); if(getTransaction(LM_API_POS_PC, dataBuffer, &dataSize))
if (dataSize == sizeof(int32_t)) {
{ m_p = unpackFXP16_16(dataBuffer);
return unpackFXP16_16(dataBuffer); }
} break;
break;
case kCurrent: case kCurrent:
getTransaction(LM_API_ICTRL_PC, dataBuffer, &dataSize); if(getTransaction(LM_API_ICTRL_PC, dataBuffer, &dataSize))
if (dataSize == sizeof(int32_t)) {
{ m_p = unpackFXP16_16(dataBuffer);
return unpackFXP16_16(dataBuffer); }
} break;
break;
} }
return 0.0;
return m_p;
} }
/** /**
@@ -717,38 +666,36 @@ double CANJaguar::GetP()
*/ */
double CANJaguar::GetI() double CANJaguar::GetI()
{ {
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
switch(m_controlMode) switch(m_controlMode)
{ {
case kPercentVbus: case kPercentVbus:
case kVoltage: case kVoltage:
wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode"); wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
break; break;
case kSpeed: case kSpeed:
getTransaction(LM_API_SPD_IC, dataBuffer, &dataSize); if(getTransaction(LM_API_SPD_IC, dataBuffer, &dataSize))
if (dataSize == sizeof(int32_t)) {
{ m_i = unpackFXP16_16(dataBuffer);
return unpackFXP16_16(dataBuffer); }
} break;
break; case kPosition:
case kPosition: if(getTransaction(LM_API_POS_IC, dataBuffer, &dataSize))
getTransaction(LM_API_POS_IC, dataBuffer, &dataSize); {
if (dataSize == sizeof(int32_t)) m_i = unpackFXP16_16(dataBuffer);
{ }
return unpackFXP16_16(dataBuffer); break;
} case kCurrent:
break; if(getTransaction(LM_API_ICTRL_IC, dataBuffer, &dataSize))
case kCurrent: {
getTransaction(LM_API_ICTRL_IC, dataBuffer, &dataSize); m_i = unpackFXP16_16(dataBuffer);
if (dataSize == sizeof(int32_t)) }
{ break;
return unpackFXP16_16(dataBuffer); }
}
break; return m_i;
}
return 0.0;
} }
/** /**
@@ -758,38 +705,36 @@ double CANJaguar::GetI()
*/ */
double CANJaguar::GetD() double CANJaguar::GetD()
{ {
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
switch(m_controlMode) switch(m_controlMode)
{ {
case kPercentVbus: case kPercentVbus:
case kVoltage: case kVoltage:
wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode"); wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
break; break;
case kSpeed: case kSpeed:
getTransaction(LM_API_SPD_DC, dataBuffer, &dataSize); if(getTransaction(LM_API_SPD_DC, dataBuffer, &dataSize))
if (dataSize == sizeof(int32_t)) {
{ m_d = unpackFXP16_16(dataBuffer);
return unpackFXP16_16(dataBuffer); }
} break;
break; case kPosition:
case kPosition: if(getTransaction(LM_API_POS_DC, dataBuffer, &dataSize))
getTransaction(LM_API_POS_DC, dataBuffer, &dataSize); {
if (dataSize == sizeof(int32_t)) m_d = unpackFXP16_16(dataBuffer);
{ }
return unpackFXP16_16(dataBuffer); break;
} case kCurrent:
break; if(getTransaction(LM_API_ICTRL_DC, dataBuffer, &dataSize))
case kCurrent: {
getTransaction(LM_API_ICTRL_DC, dataBuffer, &dataSize); m_d = unpackFXP16_16(dataBuffer);
if (dataSize == sizeof(int32_t)) }
{ break;
return unpackFXP16_16(dataBuffer); }
}
break; return m_d;
}
return 0.0;
} }
/** /**
@@ -889,12 +834,12 @@ CANJaguar::ControlMode CANJaguar::GetControlMode()
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
getTransaction(LM_API_STATUS_CMODE, dataBuffer, &dataSize); if(getTransaction(LM_API_STATUS_CMODE, dataBuffer, &dataSize))
if (dataSize == sizeof(int8_t)) {
{ m_controlMode = (ControlMode)dataBuffer[0];
return (ControlMode)dataBuffer[0]; }
}
return kPercentVbus; return m_controlMode;
} }
/** /**
@@ -907,12 +852,12 @@ float CANJaguar::GetBusVoltage()
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
getTransaction(LM_API_STATUS_VOLTBUS, dataBuffer, &dataSize); if(getTransaction(LM_API_STATUS_VOLTBUS, dataBuffer, &dataSize))
if (dataSize == sizeof(int16_t)) {
{ m_busVoltage = unpackFXP8_8(dataBuffer);
return unpackFXP8_8(dataBuffer); }
}
return 0.0; return m_busVoltage;
} }
/** /**
@@ -922,16 +867,15 @@ float CANJaguar::GetBusVoltage()
*/ */
float CANJaguar::GetOutputVoltage() float CANJaguar::GetOutputVoltage()
{ {
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
// Read the volt out which is in Volts units. if(getTransaction(LM_API_STATUS_VOUT, dataBuffer, &dataSize))
getTransaction(LM_API_STATUS_VOUT, dataBuffer, &dataSize); {
if (dataSize == sizeof(int16_t)) m_outputVoltage = unpackFXP8_8(dataBuffer);
{ }
return unpackFXP8_8(dataBuffer);
} return m_outputVoltage;
return 0.0;
} }
/** /**
@@ -941,15 +885,15 @@ float CANJaguar::GetOutputVoltage()
*/ */
float CANJaguar::GetOutputCurrent() float CANJaguar::GetOutputCurrent()
{ {
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
getTransaction(LM_API_STATUS_CURRENT, dataBuffer, &dataSize); if(getTransaction(LM_API_STATUS_CURRENT, dataBuffer, &dataSize))
if (dataSize == sizeof(int16_t)) {
{ m_outputCurrent = unpackFXP8_8(dataBuffer);
return unpackFXP8_8(dataBuffer); }
}
return 0.0; return m_outputCurrent;
} }
/** /**
@@ -959,15 +903,15 @@ float CANJaguar::GetOutputCurrent()
*/ */
float CANJaguar::GetTemperature() float CANJaguar::GetTemperature()
{ {
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
getTransaction(LM_API_STATUS_TEMP, dataBuffer, &dataSize); if(getTransaction(LM_API_STATUS_TEMP, dataBuffer, &dataSize))
if (dataSize == sizeof(int16_t)) {
{ m_temperature = unpackFXP8_8(dataBuffer);
return unpackFXP8_8(dataBuffer); }
}
return 0.0; return m_temperature;
} }
/** /**
@@ -980,12 +924,12 @@ double CANJaguar::GetPosition()
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
getTransaction(LM_API_STATUS_POS, dataBuffer, &dataSize); if(getTransaction(LM_API_STATUS_POS, dataBuffer, &dataSize))
if (dataSize == sizeof(int32_t)) {
{ m_position = unpackFXP16_16(dataBuffer);
return unpackFXP16_16(dataBuffer); }
}
return 0.0; return m_position;
} }
/** /**
@@ -998,12 +942,12 @@ double CANJaguar::GetSpeed()
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
getTransaction(LM_API_STATUS_SPD, dataBuffer, &dataSize); if(getTransaction(LM_API_STATUS_SPD, dataBuffer, &dataSize))
if (dataSize == sizeof(int32_t)) {
{ m_speed = unpackFXP16_16(dataBuffer);
return unpackFXP16_16(dataBuffer); }
}
return 0.0; return m_speed;
} }
/** /**
@@ -1016,12 +960,12 @@ bool CANJaguar::GetForwardLimitOK()
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
getTransaction(LM_API_STATUS_LIMIT, dataBuffer, &dataSize); if(getTransaction(LM_API_STATUS_LIMIT, dataBuffer, &dataSize))
if (dataSize == sizeof(uint8_t)) {
{ m_limits = dataBuffer[0];
return (*dataBuffer & kForwardLimit) != 0; }
}
return 0; return m_limits & kForwardLimit;
} }
/** /**
@@ -1031,15 +975,15 @@ bool CANJaguar::GetForwardLimitOK()
*/ */
bool CANJaguar::GetReverseLimitOK() bool CANJaguar::GetReverseLimitOK()
{ {
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
getTransaction(LM_API_STATUS_LIMIT, dataBuffer, &dataSize); if(getTransaction(LM_API_STATUS_LIMIT, dataBuffer, &dataSize))
if (dataSize == sizeof(uint8_t)) {
{ m_limits = dataBuffer[0];
return (*dataBuffer & kReverseLimit) != 0; }
}
return 0; return m_limits & kReverseLimit;
} }
/** /**
@@ -1052,14 +996,15 @@ uint16_t CANJaguar::GetFaults()
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
getTransaction(LM_API_STATUS_FAULT, dataBuffer, &dataSize); if(getTransaction(LM_API_STATUS_FAULT, dataBuffer, &dataSize))
if (dataSize == sizeof(uint16_t)) {
{ m_faults = unpackint16_t(dataBuffer);;
return unpackint16_t(dataBuffer); }
}
return 0; return m_faults;
} }
#if 0
/** /**
* Check if the Jaguar's power has been cycled since this was last called. * Check if the Jaguar's power has been cycled since this was last called.
* *
@@ -1089,6 +1034,7 @@ bool CANJaguar::GetPowerCycled()
} }
return 0; return 0;
} }
#endif
/** /**
* Set the maximum voltage change rate. * Set the maximum voltage change rate.
@@ -1125,16 +1071,16 @@ void CANJaguar::SetVoltageRampRate(double rampRate)
*/ */
uint32_t CANJaguar::GetFirmwareVersion() uint32_t CANJaguar::GetFirmwareVersion()
{ {
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
// Set the MSB to tell the 2CAN that this is a remote message. // Set the MSB to tell the 2CAN that this is a remote message.
getTransaction(0x80000000 | CAN_MSGID_API_FIRMVER, dataBuffer, &dataSize); if(getTransaction(0x80000000 | CAN_MSGID_API_FIRMVER, dataBuffer, &dataSize))
if (dataSize == sizeof(uint32_t)) {
{ m_firmwareVersion = unpackint32_t(dataBuffer);
return unpackint32_t(dataBuffer); }
}
return 0; return m_firmwareVersion;
} }
/** /**
@@ -1147,16 +1093,13 @@ uint8_t CANJaguar::GetHardwareVersion()
uint8_t dataBuffer[8]; uint8_t dataBuffer[8];
uint8_t dataSize; uint8_t dataSize;
getTransaction(LM_API_HWVER, dataBuffer, &dataSize); // Only get once, since this shoudn't change.
if (dataSize == sizeof(uint8_t)+sizeof(uint8_t)) if(!m_hardwareVersion && getTransaction(LM_API_HWVER, dataBuffer, &dataSize))
{ {
if (*dataBuffer == m_deviceNumber) m_hardwareVersion = *(dataBuffer+1);
{ }
return *(dataBuffer+1);
} return m_hardwareVersion;
}
// Assume Gray Jag if there is no response
return LM_HWVER_JAG_1_0;
} }
/** /**
@@ -1337,37 +1280,47 @@ void CANJaguar::StopMotor()
DisableControl(); DisableControl();
} }
void CANJaguar::ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew) { void CANJaguar::ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew)
{
Set(value.f); Set(value.f);
} }
void CANJaguar::UpdateTable() { void CANJaguar::UpdateTable()
if (m_table != NULL) { {
if (m_table != NULL)
{
m_table->PutNumber("Value", Get()); m_table->PutNumber("Value", Get());
} }
} }
void CANJaguar::StartLiveWindowMode() { void CANJaguar::StartLiveWindowMode()
if (m_table != NULL) { {
if (m_table != NULL)
{
m_table->AddTableListener("Value", this, true); m_table->AddTableListener("Value", this, true);
} }
} }
void CANJaguar::StopLiveWindowMode() { void CANJaguar::StopLiveWindowMode()
if (m_table != NULL) { {
if (m_table != NULL)
{
m_table->RemoveTableListener(this); m_table->RemoveTableListener(this);
} }
} }
std::string CANJaguar::GetSmartDashboardType() { std::string CANJaguar::GetSmartDashboardType()
{
return "Speed Controller"; return "Speed Controller";
} }
void CANJaguar::InitTable(ITable *subTable) { void CANJaguar::InitTable(ITable *subTable)
{
m_table = subTable; m_table = subTable;
UpdateTable(); UpdateTable();
} }
ITable * CANJaguar::GetTable() { ITable * CANJaguar::GetTable()
{
return m_table; return m_table;
} }

View File

@@ -42,4 +42,7 @@ public:
static const uint32_t kFakePressureSwitchChannel = 11; static const uint32_t kFakePressureSwitchChannel = 11;
static const uint32_t kFakeSolenoid1Channel = 12; static const uint32_t kFakeSolenoid1Channel = 12;
static const uint32_t kFakeSolenoid2Channel = 13; static const uint32_t kFakeSolenoid2Channel = 13;
/* CAN IDs */
static const uint32_t kCANJaguarID = 1;
}; };

View File

@@ -0,0 +1,44 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2014. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "WPILib.h"
#include "gtest/gtest.h"
#include "TestBench.h"
class CANJaguarTest : public testing::Test {
protected:
CANJaguar *m_jaguar;
virtual void SetUp() {
Wait(0.04);
m_jaguar = new CANJaguar(TestBench::kCANJaguarID);
}
virtual void TearDown() {
delete m_jaguar;
}
void Reset() {
m_jaguar->ChangeControlMode(CANJaguar::kPercentVbus);
m_jaguar->Set(0.0f);
}
};
#if 0
TEST_F(CANJaguarTest, Speed) {
Reset();
for(;;) {
m_jaguar->Set(1.0f);
std::cout << "Temperature = " << m_jaguar->GetTemperature() << std::endl;
std::cout << "Current = " << m_jaguar->GetOutputCurrent() << std::endl;
Wait(0.1);
}
}
#endif