PDP and PCM updated to rely on CtreCanNode parent class, which uses new CAN API.

CtreCanNode registers the periodic tx messages and provides an rx function to child classes for easy getters and setters.
Some template magic to make the PDP and PCM getters/setters easy to stamp out.

Change-Id: Ibdd0745af070756a282df5074504491fadfde336
This commit is contained in:
Omar Zrien
2014-06-29 16:49:00 -04:00
committed by thomasclark
parent ff8016c088
commit 0ef5c3adfa
7 changed files with 580 additions and 615 deletions

View File

@@ -1,16 +1,93 @@
#if 0
#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;
#define STATUS_1 0x9041400
#define STATUS_SOL_FAULTS 0x9041440
#define STATUS_DEBUG 0x9041480
#define EXPECTED_RESPONSE_TIMEOUT_MS (50)
#define GET_PCM_STATUS() CtreCanNode::recMsg<PcmStatus_t> rx = GetRx<PcmStatus_t> (STATUS_1,EXPECTED_RESPONSE_TIMEOUT_MS)
#define GET_PCM_SOL_FAULTS() CtreCanNode::recMsg<PcmStatusFault_t> rx = GetRx<PcmStatusFault_t> (STATUS_SOL_FAULTS,EXPECTED_RESPONSE_TIMEOUT_MS)
#define GET_PCM_DEBUG() CtreCanNode::recMsg<PcmDebug_t> rx = GetRx<PcmDebug_t> (STATUS_DEBUG,EXPECTED_RESPONSE_TIMEOUT_MS)
#define CONTROL_1 0x09041C00
/* encoder/decoders */
typedef struct _PcmStatus_t{
/* Byte 0 */
unsigned SolenoidBits:8;
/* Byte 1 */
unsigned compressorOn:1;
unsigned stickyFaultFuseTripped:1;
unsigned stickyFaultCompCurrentTooHigh:1;
unsigned faultCompCurrentTooHigh:1;
unsigned faultFuseTripped:1;
unsigned faultHardwareFailure:1;
unsigned isCloseloopEnabled:1;
unsigned pressureSwitchEn:1;
/* Byte 2*/
unsigned battVoltage:8;
/* Byte 3 */
unsigned solenoidVoltageTop8:8;
/* Byte 4 */
unsigned compressorCurrentTop6:6;
unsigned solenoidVoltageBtm2:2;
/* Byte 5 */
unsigned reserved:2;
unsigned moduleEnabled:1;
unsigned closedLoopOutput:1;
unsigned compressorCurrentBtm4:4;
/* Byte 6 */
unsigned tokenSeedTop8:8;
/* Byte 7 */
unsigned tokenSeedBtm8:8;
}PcmStatus_t;
typedef struct _PcmControl_t{
/* Byte 0 */
unsigned tokenTop8:8;
/* Byte 1 */
unsigned tokenBtm8:8;
/* Byte 2 */
unsigned solenoidBits:8;
/* Byte 3*/
unsigned reserved:4;
unsigned closeLoopOutput:1;
unsigned compressorOn:1;
unsigned closedLoopEnable:1;
unsigned clearStickyFaults:1;
}PcmControl_t;
typedef struct _PcmStatusFault_t{
/* Byte 0 */
unsigned SolenoidBlacklist:8;
/* Byte 1 */
unsigned reserved1:8;
unsigned reserved2:8;
unsigned reserved3:8;
unsigned reserved4:8;
unsigned reserved5:8;
unsigned reserved6:8;
unsigned reserved7:8;
}PcmStatusFault_t;
typedef struct _PcmDebug_t{
unsigned tokFailsTop8:8;
unsigned tokFailsBtm8:8;
unsigned lastFailedTokTop8:8;
unsigned lastFailedTokBtm8:8;
unsigned tokSuccessTop8:8;
unsigned tokSuccessBtm8:8;
}PcmDebug_t;
/* PCM Constructor - Clears all vars, establishes default settings, starts PCM background process
*
@@ -18,60 +95,39 @@ static const INT32 kCANPeriod = 20;
*
* @Param - deviceNumber - Device ID of PCM to be controlled
*/
PCM::PCM(UINT8 deviceNumber)
PCM::PCM(UINT8 deviceNumber): CtreCanNode(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);
RegisterRx(STATUS_1 | deviceNumber );
RegisterRx(STATUS_SOL_FAULTS | deviceNumber );
RegisterRx(STATUS_DEBUG | deviceNumber );
RegisterTx(CONTROL_1 | deviceNumber, kCANPeriod);
/* enable close loop */
CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());
toFill->closedLoopEnable = 1;
}
/* 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);
PCM::~PCM()
{
}
/* Set PCM solenoid state
*
* @Return - CTR_Code - Error code (if any) for setting solenoid
*
* @Param - idx - ID of solenoid (1-8)
* @Param - idx - ID of solenoid (0-7)
* @Param - en - Enable / Disable identified solenoid
*/
CTR_Code PCM::SetSolenoid(unsigned char idx, bool en) {
idx--; /* make it zero based */
CTR_Code PCM::SetSolenoid(unsigned char idx, bool en)
{
CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());
if(toFill.IsEmpty())return CTR_UnexpectedArbId;
if (en)
_PcmControl.solenoidBits |= (1ul << (7-idx));
toFill->solenoidBits |= (1ul << (7-idx));
else
_PcmControl.solenoidBits &= ~(1ul << (7-idx));
if (GetTimeSinceLastTx() >= 50)
return CTR_TxTimeout;
toFill->solenoidBits &= ~(1ul << (7-idx));
FlushTx(toFill);
return CTR_OKAY;
}
@@ -81,10 +137,12 @@ CTR_Code PCM::SetSolenoid(unsigned char idx, bool en) {
*
* @Param - clr - Clear / do not clear faults
*/
CTR_Code PCM::ClearStickyFaults(bool clr) {
_PcmControl.clearStickyFaults = clr;
if (GetTimeSinceLastTx() >= 50)
return CTR_TxTimeout;
CTR_Code PCM::ClearStickyFaults(bool clr)
{
CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());
if(toFill.IsEmpty())return CTR_UnexpectedArbId;
toFill->clearStickyFaults = clr;
FlushTx(toFill);
return CTR_OKAY;
}
@@ -94,299 +152,212 @@ CTR_Code PCM::ClearStickyFaults(bool clr) {
*
* @Param - en - Enable / Disable Closed Loop Control
*/
CTR_Code PCM::SetClosedLoopControl(bool en) {
_PcmControl.closedLoopEnable = en;
if (GetTimeSinceLastTx() >= 50)
return CTR_TxTimeout;
CTR_Code PCM::SetClosedLoopControl(bool en)
{
CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());
if(toFill.IsEmpty())return CTR_UnexpectedArbId;
toFill->closedLoopEnable = en;
FlushTx(toFill);
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
*
* @Param - idx - ID of solenoid (0-7) 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;
CTR_Code PCM::GetSolenoid(UINT8 idx, bool &status)
{
GET_PCM_STATUS();
status = (rx->SolenoidBits & (1ul<<(7-idx)) ) ? 1 : 0;
return rx.err;
}
/* 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;
CTR_Code PCM::GetPressure(bool &status)
{
GET_PCM_STATUS();
status = (rx->pressureSwitchEn ) ? 1 : 0;
return rx.err;
}
/* 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;
CTR_Code PCM::GetCompressor(bool &status)
{
GET_PCM_STATUS();
status = (rx->compressorOn);
return rx.err;
}
/* 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;
CTR_Code PCM::GetClosedLoopControl(bool &status)
{
GET_PCM_STATUS();
status = (rx->isCloseloopEnabled);
return rx.err;
}
/* Get compressor current draw
*
* @Return - Amperes - Compressor current
*
* @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;
CTR_Code PCM::GetCompressorCurrent(float &status)
{
GET_PCM_STATUS();
uint32_t temp =(rx->compressorCurrentTop6);
temp <<= 4;
temp |= rx->compressorCurrentBtm4;
status = 20.1612903225806 * temp;
return rx.err;
}
/* Get voltage across solenoid rail
*
*
* @Return - Volts - Voltage across solenoid rail
*/
CTR_Code PCM::GetSolenoidVoltage(float &status) {
uint32_t raw = _PcmStatus.solenoidVoltageTop8;
CTR_Code PCM::GetSolenoidVoltage(float &status)
{
GET_PCM_STATUS();
uint32_t raw =(rx->solenoidVoltageTop8);
raw <<= 2;
raw |= _PcmStatus.solenoidVoltageBtm2;
raw |= rx->solenoidVoltageBtm2;
status = (double) raw * 24.7800586510264 / 1000;
if (GetTimeSinceLastRx() >= 50)
return CTR_RxTimeout;
return CTR_OKAY;
return rx.err;
}
/* 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;
CTR_Code PCM::GetHardwareFault(bool &status)
{
GET_PCM_STATUS();
status = rx->faultHardwareFailure;
return rx.err;
}
/* 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;
CTR_Code PCM::GetCompressorFault(bool &status)
{
GET_PCM_STATUS();
status = rx->faultCompCurrentTooHigh;
return rx.err;
}
/* 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;
CTR_Code PCM::GetSolenoidFault(bool &status)
{
GET_PCM_STATUS();
status = rx->faultFuseTripped;
return rx.err;
}
// 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;
CTR_Code PCM::GetCompressorStickyFault(bool &status)
{
GET_PCM_STATUS();
status = rx->stickyFaultCompCurrentTooHigh;
return rx.err;
}
/* 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;
CTR_Code PCM::GetSolenoidStickyFault(bool &status)
{
GET_PCM_STATUS();
status = rx->stickyFaultFuseTripped;
return rx.err;
}
/* 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;
CTR_Code PCM::GetBatteryVoltage(float &status)
{
GET_PCM_STATUS();
status = (float)rx->battVoltage * ((59.0420332355816) / 1000.0);;
return rx.err;
}
/* 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)
CTR_Code PCM::isModuleEnabled(bool &status)
{
if(timeSinceLastRx) *timeSinceLastRx = _timeSinceLastRx;
if(timeSinceLastTx) *timeSinceLastTx = _timeSinceLastTx;
if(numFailedRxs) *numFailedRxs = _numFailedRxs;
if(numFailedTxs) *numFailedTxs = _numFailedTxs;
GET_PCM_STATUS();
status = rx->moduleEnabled;
return rx.err;
}
//------------------ 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()
/* 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)
{
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;
GET_PCM_DEBUG();
status = rx->tokFailsTop8;
status <<= 8;
status |= rx->tokFailsBtm8;
return rx.err;
}
void * PCM::ThreadFunc( void *ptr )
/* 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)
{
return ((PCM*)ptr)->ThreadFunc();
GET_PCM_SOL_FAULTS();
status = rx->SolenoidBlacklist;
return rx.err;
}
/* 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 [0,7]
*
* @WARNING - Return only valid if [SeekStatusFaultFrames] is enabled
* See function SeekStatusFaultFrames
* See function EnableSeekStatusFaultFrames
*/
CTR_Code PCM::IsSolenoidBlacklisted(UINT8 idx, bool &status)
{
GET_PCM_SOL_FAULTS();
status = (rx->SolenoidBlacklist & (1ul<<(7-idx)) )? 1 : 0;
return rx.err;
}
//------------------ C interface --------------------------------------------//
extern "C" {
@@ -430,7 +401,6 @@ extern "C" {
CTR_Code retval = ((PCM*) handle)->GetCompressorCurrent(*status);
return retval;
}
CTR_Code c_GetSolenoidVoltage(void * handle, float*status) {
return ((PCM*) handle)->GetSolenoidVoltage(*status);
}
@@ -469,7 +439,6 @@ extern "C" {
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);
@@ -484,3 +453,4 @@ extern "C" {
return retval;
}
}
#endif