Files
allwpilib/hal/lib/Athena/ctre/PCM.cpp
thomasclark 85dff7d2ec 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
2014-06-16 10:24:48 -04:00

487 lines
14 KiB
C++

#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#include "PCM.h"
#include "NetworkCommunication/CANSessionMux.h"
#include <string.h> // memset
#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
*
* @Return - void
*
* @Param - deviceNumber - Device ID of PCM to be controlled
*/
PCM::PCM(UINT8 deviceNumber)
{
memset(&_PcmDebug, 0, sizeof(_PcmDebug));
memset(&_PcmControl, 0, sizeof(_PcmControl));
memset(&_PcmStatus, 0, sizeof(_PcmStatus));
memset(&_PcmStatusFault,0, sizeof(_PcmStatusFault));
/* setup arbids */
SetDeviceNumber(deviceNumber);
/* clear error info */
_timeSinceLastRx = 0;
_timeSinceLastTx = 0;
_numFailedRxs = 0;
_numFailedTxs = 0;
/* start thread */
_threadIsRunning = 1;
_threadErr = pthread_create( &_thread, NULL, ThreadFunc, (void*) this);
}
/* PCM D'tor
*/
PCM::~PCM() {
/* wait for thread to finish */
_threadIsRunning = 0;
pthread_join( _thread, NULL);
_thread = 0;
}
/* Set PCM Device Number and according CAN frame IDs
*
* @Return - void
*
* @Param - deviceNumber - Device number of PCM to control
*/
void PCM::SetDeviceNumber(UINT8 deviceNumber) {
PCM_settings.deviceNumber = deviceNumber;
PCM_settings.controlFrameID = 0x9041C00 + (deviceNumber) + (UINT32) (0 * BIT6);
PCM_settings.statusFrameID = 0x9041400 + (deviceNumber) + (UINT32) (0 * BIT6);
PCM_settings.statusFaultFrameID = 0x9041400 + (deviceNumber) + (UINT32) (1 * BIT6);
PCM_settings.debugFrameID = 0x9041400 + (deviceNumber) + (UINT32) (2 * BIT6);
}
/* Set PCM solenoid state
*
* @Return - CTR_Code - Error code (if any) for setting solenoid
*
* @Param - idx - ID of solenoid (1-8)
* @Param - en - Enable / Disable identified solenoid
*/
CTR_Code PCM::SetSolenoid(unsigned char idx, bool en) {
idx--; /* make it zero based */
if (en)
_PcmControl.solenoidBits |= (1ul << (7-idx));
else
_PcmControl.solenoidBits &= ~(1ul << (7-idx));
if (GetTimeSinceLastTx() >= 50)
return CTR_TxTimeout;
return CTR_OKAY;
}
/* Clears PCM sticky faults (indicators of past faults
*
* @Return - CTR_Code - Error code (if any) for setting solenoid
*
* @Param - clr - Clear / do not clear faults
*/
CTR_Code PCM::ClearStickyFaults(bool clr) {
_PcmControl.clearStickyFaults = clr;
if (GetTimeSinceLastTx() >= 50)
return CTR_TxTimeout;
return CTR_OKAY;
}
/* Enables PCM Closed Loop Control of Compressor via pressure switch
*
* @Return - CTR_Code - Error code (if any) for setting solenoid
*
* @Param - en - Enable / Disable Closed Loop Control
*/
CTR_Code PCM::SetClosedLoopControl(bool en) {
_PcmControl.closedLoopEnable = en;
if (GetTimeSinceLastTx() >= 50)
return CTR_TxTimeout;
return CTR_OKAY;
}
/* Get solenoid state
*
* @Return - True/False - True if solenoid enabled, false otherwise
*
* @Param - idx - ID of solenoid (1-8) to return status of
*/
CTR_Code PCM::GetSolenoid(UINT8 idx, bool &status) {
idx--;
status = (_PcmStatus.SolenoidBits & (1ul<<(7-idx))) ? 1 : 0;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get pressure switch state
*
* @Return - True/False - True if pressure adequate, false if low
*/
CTR_Code PCM::GetPressure(bool &status) {
status = _PcmStatus.pressureSwitchEn;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get compressor state
*
* @Return - True/False - True if enabled, false if otherwise
*/
CTR_Code PCM::GetCompressor(bool &status) {
status = _PcmStatus.compressorOn;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get closed loop control state
*
* @Return - True/False - True if closed loop enabled, false if otherwise
*/
CTR_Code PCM::GetClosedLoopControl(bool &status) {
status = _PcmStatus.isCloseloopEnabled;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get compressor current draw
*
* @Return - Amperes - Compressor current
*/
CTR_Code PCM::GetCompressorCurrent(float &status) {
uint16_t bt = _PcmStatus.compressorCurrentTop6;
bt <<= 4;
bt |= _PcmStatus.compressorCurrentBtm4;
status = 0.0201612903225806 * bt;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get voltage across solenoid rail
*
* @Return - Volts - Voltage across solenoid rail
*/
CTR_Code PCM::GetSolenoidVoltage(float &status) {
uint32_t raw = _PcmStatus.solenoidVoltageTop8;
raw <<= 2;
raw |= _PcmStatus.solenoidVoltageBtm2;
status = (double) raw * 24.7800586510264 / 1000;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get hardware fault value
*
* @Return - True/False - True if hardware failure detected, false if otherwise
*/
CTR_Code PCM::GetHardwareFault(bool &status) {
status = _PcmStatus.faultHardwareFailure;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get compressor fault value
*
* @Return - True/False - True if shorted compressor detected, false if otherwise
*/
CTR_Code PCM::GetCompressorFault(bool &status) {
status = _PcmStatus.faultCompCurrentTooHigh;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get solenoid fault value
*
* @Return - True/False - True if shorted solenoid detected, false if otherwise
*/
CTR_Code PCM::GetSolenoidFault(bool &status) {
status = _PcmStatus.faultFuseTripped;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
// Past Faults
/* Get compressor sticky fault value
*
* @Return - True/False - True if solenoid had previously been shorted
* (and sticky fault was not cleared), false if otherwise
*/
CTR_Code PCM::GetCompressorStickyFault(bool &status) {
status = _PcmStatus.stickyFaultCompCurrentTooHigh;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get solenoid sticky fault value
*
* @Return - True/False - True if compressor had previously been shorted
* (and sticky fault was not cleared), false if otherwise
*/
CTR_Code PCM::GetSolenoidStickyFault(bool &status) { /* fix this */
status = _PcmStatus.stickyFaultFuseTripped;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get battery voltage
*
* @Return - Volts - Voltage across PCM power ports
*/
CTR_Code PCM::GetBatteryVoltage(float &status) {
status = (float)_PcmStatus.battVoltage * ((59.0420332355816) / 1000.0);;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get number of total failed PCM Control Frame
*
* @Return - Failed Control Frames - Number of failed control frames (tokenization fails)
*
* @WARNING - Return only valid if [SeekDebugFrames] is enabled
* See function SeekDebugFrames
* See function EnableSeekDebugFrames
*/
CTR_Code PCM::GetNumberOfFailedControlFrames(UINT16 &status) {
status = _PcmDebug.tokFailsTop8;
status <<= 8;
status |= _PcmDebug.tokFailsBtm8;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get raw Solenoid Blacklist
*
* @Return - BINARY - Raw binary breakdown of Solenoid Blacklist
* BIT7 = Solenoid 1, BIT6 = Solenoid 2, etc.
*
* @WARNING - Return only valid if [SeekStatusFaultFrames] is enabled
* See function SeekStatusFaultFrames
* See function EnableSeekStatusFaultFrames
*/
CTR_Code PCM::GetSolenoidBlackList(UINT8 &status) {
status = _PcmStatusFault.SolenoidBlacklist;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Get solenoid Blacklist status
* - Blacklisted solenoids cannot be enabled until PCM is power cycled
*
* @Return - True/False - True if Solenoid is blacklisted, false if otherwise
*
* @Param - idx - ID of solenoid
*
* @WARNING - Return only valid if [SeekStatusFaultFrames] is enabled
* See function SeekStatusFaultFrames
* See function EnableSeekStatusFaultFrames
*/
CTR_Code PCM::IsSolenoidBlacklisted(UINT8 idx, bool &status) {
idx--;
if(_PcmStatusFault.SolenoidBlacklist & (1ul<<(7-idx)))
status = 1;
else
status = 0;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
/* Return status of module enable/disable
*
* @Return - bool - Returns TRUE if PCM is enabled, FALSE if disabled
*/
CTR_Code PCM::isModuleEnabled(bool &status) {
status = _PcmStatus.moduleEnabled;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
}
void PCM::GetErrorInfo( uint32_t * timeSinceLastRx,
uint32_t * timeSinceLastTx,
uint32_t * numFailedRxs,
uint32_t * numFailedTxs)
{
if(timeSinceLastRx) *timeSinceLastRx = _timeSinceLastRx;
if(timeSinceLastTx) *timeSinceLastTx = _timeSinceLastTx;
if(numFailedRxs) *numFailedRxs = _numFailedRxs;
if(numFailedTxs) *numFailedTxs = _numFailedTxs;
}
//------------------ CAN interface and thread --------------------------------------------//
/* Search for PCM Status Frame on CAN bus */
void PCM::ReadStatusFrame(void) {
PcmStatus_t frame = {0};
UINT8 size = 0;
INT32 status = 0;
UINT32 timeStamp = 0;
FRC_NetworkCommunication_CANSessionMux_receiveMessage(&PCM_settings.statusFrameID, kFullMessageIDMask, (uint8_t *)&frame, &size, &timeStamp, &status);
if (status == 0) {
_timeSinceLastRx = 0;
_PcmStatus = frame;
} else {
++_numFailedRxs;
}
}
/* Search for PCM Status Fault Frame on CAN bus */
void PCM::ReadStatusFaultFrame(void) {
PcmStatusFault_t frame= {0};
UINT8 size = 0;
INT32 status = 0;
UINT32 timeStamp = 0;
FRC_NetworkCommunication_CANSessionMux_receiveMessage(&PCM_settings.statusFaultFrameID, kFullMessageIDMask, (uint8_t *)&frame, &size, &timeStamp, &status);
if (status == 0) {
_timeSinceLastRx = 0;
_PcmStatusFault = frame;
} else {
++_numFailedRxs;
}
}
/* Search for PCM Debug Frame on CAN bus */
void PCM::ReadDebugFrame(void) {
PcmDebug_t frame= {0};
UINT8 size = 0;
INT32 status = 0;
UINT32 timeStamp = 0;
FRC_NetworkCommunication_CANSessionMux_receiveMessage(&PCM_settings.debugFrameID, kFullMessageIDMask, (uint8_t *)&frame, &size, &timeStamp, &status);
if (status == 0) {
_timeSinceLastRx = 0;
_PcmDebug = frame;
} else {
++_numFailedRxs;
}
}
void * PCM::ThreadFunc()
{
while(_threadIsRunning){
int32_t status = 0;
FRC_NetworkCommunication_CANSessionMux_sendMessage(PCM_settings.controlFrameID, (const uint8_t *)&_PcmControl, sizeof(_PcmControl), kCANPeriod, &status);
if(status == 0){
/* success */
_timeSinceLastTx = 0;
}else {
/* something is wrong */
++_numFailedTxs;
}
/* reads */
ReadStatusFrame();
ReadStatusFaultFrame();
ReadDebugFrame();
/* yield for 25ms */
usleep(25e3);
/* incrememnt times since comm without overflow */
if(_timeSinceLastTx < 60000)
_timeSinceLastTx += 25;
if(_timeSinceLastRx < 60000)
_timeSinceLastRx += 25;
}
return 0;
}
void * PCM::ThreadFunc( void *ptr )
{
return ((PCM*)ptr)->ThreadFunc();
}
//------------------ C interface --------------------------------------------//
extern "C" {
void * c_PCM_Init(void) {
return new PCM();
}
CTR_Code c_SetSolenoid(void * handle, unsigned char idx, INT8 param) {
return ((PCM*) handle)->SetSolenoid(idx, param);
}
CTR_Code c_SetClosedLoopControl(void * handle, INT8 param) {
return ((PCM*) handle)->SetClosedLoopControl(param);
}
CTR_Code c_ClearStickyFaults(void * handle, INT8 param) {
return ((PCM*) handle)->ClearStickyFaults(param);
}
CTR_Code c_GetSolenoid(void * handle, UINT8 idx, INT8 * status) {
bool bstatus;
CTR_Code retval = ((PCM*) handle)->GetSolenoid(idx, bstatus);
*status = bstatus;
return retval;
}
CTR_Code c_GetPressure(void * handle, INT8 * status) {
bool bstatus;
CTR_Code retval = ((PCM*) handle)->GetPressure(bstatus);
*status = bstatus;
return retval;
}
CTR_Code c_GetCompressor(void * handle, INT8 * status) {
bool bstatus;
CTR_Code retval = ((PCM*) handle)->GetCompressor(bstatus);
*status = bstatus;
return retval;
}
CTR_Code c_GetClosedLoopControl(void * handle, INT8 * status) {
bool bstatus;
CTR_Code retval = ((PCM*) handle)->GetClosedLoopControl(bstatus);
*status = bstatus;
return retval;
}
CTR_Code c_GetCompressorCurrent(void * handle, float * status) {
CTR_Code retval = ((PCM*) handle)->GetCompressorCurrent(*status);
return retval;
}
CTR_Code c_GetSolenoidVoltage(void * handle, float*status) {
return ((PCM*) handle)->GetSolenoidVoltage(*status);
}
CTR_Code c_GetHardwareFault(void * handle, INT8*status) {
bool bstatus;
CTR_Code retval = ((PCM*) handle)->GetHardwareFault(bstatus);
*status = bstatus;
return retval;
}
CTR_Code c_GetCompressorFault(void * handle, INT8*status) {
bool bstatus;
CTR_Code retval = ((PCM*) handle)->GetCompressorFault(bstatus);
*status = bstatus;
return retval;
}
CTR_Code c_GetSolenoidFault(void * handle, INT8*status) {
bool bstatus;
CTR_Code retval = ((PCM*) handle)->GetSolenoidFault(bstatus);
*status = bstatus;
return retval;
}
CTR_Code c_GetCompressorStickyFault(void * handle, INT8*status) {
bool bstatus;
CTR_Code retval = ((PCM*) handle)->GetCompressorStickyFault(bstatus);
*status = bstatus;
return retval;
}
CTR_Code c_GetSolenoidStickyFault(void * handle, INT8*status) {
bool bstatus;
CTR_Code retval = ((PCM*) handle)->GetSolenoidStickyFault(bstatus);
*status = bstatus;
return retval;
}
CTR_Code c_GetBatteryVoltage(void * handle, float*status) {
CTR_Code retval = ((PCM*) handle)->GetBatteryVoltage(*status);
return retval;
}
void c_SetDeviceNumber_PCM(void * handle, UINT8 deviceNumber) {
return ((PCM*) handle)->SetDeviceNumber(deviceNumber);
}
CTR_Code c_GetNumberOfFailedControlFrames(void * handle, UINT16*status) {
return ((PCM*) handle)->GetNumberOfFailedControlFrames(*status);
}
CTR_Code c_GetSolenoidBlackList(void * handle, UINT8 *status) {
return ((PCM*) handle)->GetSolenoidBlackList(*status);
}
CTR_Code c_IsSolenoidBlacklisted(void * handle, UINT8 idx, INT8*status) {
bool bstatus;
CTR_Code retval = ((PCM*) handle)->IsSolenoidBlacklisted(idx, bstatus);
*status = bstatus;
return retval;
}
}