Files
allwpilib/hal/lib/Athena/ctre/PDP.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

169 lines
5.2 KiB
C++

#include "PDP.h"
#include "NetworkCommunication/CANSessionMux.h" //CAN Comm
#include <string.h> // memset
#include <unistd.h> // usleep
#define kFullMessageIDMask 0x1fffffff
PDP::PDP(UINT8 deviceNumber)
{
memset(&_status1, 0, sizeof(_status1));
memset(&_status2, 0, sizeof(_status2));
memset(&_status3, 0, sizeof(_status3));
memset(&PDP_Settings, 0, sizeof PDP_Settings);
/* setup arbids */
SetDeviceNumber(deviceNumber);
/* clear error info */
_timeSinceLastRx = 0;
_numFailedRxs = 0;
/* start thread */
_threadIsRunning = 1;
_threadErr = pthread_create( &_thread, NULL, ThreadFunc, (void*) this);
}
/* PDP D'tor
*/
PDP::~PDP() {
/* wait for thread to finish */
_threadIsRunning = 0;
pthread_join( _thread, NULL);
_thread = 0;
}
CTR_Code PDP::GetChannelCurrent(UINT8 idx, double &current){
/* atomically copy out our data */
PdpStatus1_t status1 = _status1;
PdpStatus2_t status2 = _status2;
PdpStatus3_t status3 = _status3;
uint32_t raw = 0;
if(idx <= 6)
{
switch(idx)
{
case 0: raw = 0; break;
case 1: raw = ((uint32_t)status1.chan1_h8 << 2) | status1.chan1_l2; break;
case 2: raw = ((uint32_t)status1.chan2_h6 << 4) | status1.chan2_l4; break;
case 3: raw = ((uint32_t)status1.chan3_h4 << 6) | status1.chan3_l6; break;
case 4: raw = ((uint32_t)status1.chan4_h2 << 8) | status1.chan4_l8; break;
case 5: raw = ((uint32_t)status1.chan5_h8 << 2) | status1.chan5_l2; break;
case 6: raw = ((uint32_t)status1.chan6_h6 << 4) | status1.chan6_l4; break;
}
}
else if(idx <= 12)
{
switch(idx)
{
case 7: raw = ((uint32_t)status2.chan7_h8 << 2) | status2.chan7_l2; break;
case 8: raw = ((uint32_t)status2.chan8_h6 << 4) | status2.chan8_l4; break;
case 9: raw = ((uint32_t)status2.chan9_h4 << 6) | status2.chan9_l6; break;
case 10: raw = ((uint32_t)status2.chan10_h2 << 8) | status2.chan10_l8; break;
case 11: raw = ((uint32_t)status2.chan11_h8 << 2) | status2.chan11_l2; break;
case 12: raw = ((uint32_t)status2.chan12_h6 << 4) | status2.chan12_l4; break;
}
}
else if(idx <= 16)
{
switch(idx)
{
case 13: raw = ((uint32_t)status3.chan13_h8 << 2) | status3.chan13_l2; break;
case 14: raw = ((uint32_t)status3.chan14_h6 << 4) | status3.chan14_l4; break;
case 15: raw = ((uint32_t)status3.chan15_h4 << 6) | status3.chan15_l6; break;
case 16: raw = ((uint32_t)status3.chan16_h2 << 8) | status3.chan16_l8; break;
}
}
/* convert to amps */
current = 0.06724511900000001*raw + 1.527114967;
/* signal caller with success */
if(GetTimeSinceLastRx()>=50)
return CTR_RxTimeout;
return CTR_OKAY;
}
CTR_Code PDP::GetVoltage(double &voltage){
uint32_t raw = _status3.busVoltage;
voltage = 0.0554413328606877 * raw;
if(GetTimeSinceLastRx()>=50)
return CTR_RxTimeout;
return CTR_OKAY;
}
CTR_Code PDP::GetTemperature(double &tempC){
uint32_t raw = _status3.temp;
tempC = ((double)raw-67.8564500484966)*1.03250836957542;
if(GetTimeSinceLastRx()>=50)
return CTR_RxTimeout;
return CTR_OKAY;
}
void PDP::SetDeviceNumber(UINT8 deviceNumber){
PDP_Settings.deviceNumber = deviceNumber;
PDP_Settings.frameIDs[0] = 0x8041400 + (deviceNumber) + (UINT32) (0 * BIT6);
PDP_Settings.frameIDs[1] = 0x8041400 + (deviceNumber) + (UINT32) (1 * BIT6);
PDP_Settings.frameIDs[2] = 0x8041400 + (deviceNumber) + (UINT32) (2 * BIT6);
}
void PDP::GetErrorInfo( uint32_t * timeSinceLastRx,
uint32_t * numFailedRxs)
{
if(timeSinceLastRx) *timeSinceLastRx = _timeSinceLastRx;
if(numFailedRxs) *numFailedRxs = _numFailedRxs;
}
//------------------ CAN interface and thread --------------------------------------------//
/* Search for PCM Status Frame on CAN bus */
uint64_t PDP::ReadCurrents(uint8_t api)
{
uint64_t frame = 0;
UINT8 size = 0;
INT32 status = 0;
UINT32 timeStamp = 0;
FRC_NetworkCommunication_CANSessionMux_receiveMessage(&PDP_Settings.frameIDs[api], kFullMessageIDMask, (uint8_t *)&frame, &size, &timeStamp, &status);
if (status == 0) {
_timeSinceLastRx = 0;
} else {
++_numFailedRxs;
}
return frame;
}
void * PDP::ThreadFunc()
{
while(_threadIsRunning){
/* reads */
uint64_t frame1 = ReadCurrents(0);
uint64_t frame2 = ReadCurrents(1);
uint64_t frame3 = ReadCurrents(2);
/* update stats */
memcpy(&_status1,&frame1,8);
memcpy(&_status2,&frame2,8);
memcpy(&_status3,&frame3,8);
/* yield for 25ms */
usleep(25e3);
/* timeouts */
if(_timeSinceLastRx < 60000)
_timeSinceLastRx += 20;
}
return 0;
}
void * PDP::ThreadFunc( void *ptr )
{
return ((PDP*)ptr)->ThreadFunc();
}
//------------------ C interface --------------------------------------------//
extern "C" {
void * c_PDP_Init(void)
{
return new PDP();
}
CTR_Code c_GetChannelCurrent(void * handle,UINT8 idx, double *status)
{
return ((PDP*)handle)-> GetChannelCurrent(idx,*status);
}
CTR_Code c_GetVoltage(void * handle,double *status)
{
return ((PDP*)handle)-> GetVoltage(*status);
}
CTR_Code c_GetTemperature(void * handle,double *status)
{
return ((PDP*)handle)-> GetTemperature(*status);
}
void c_SetDeviceNumber_PDP(void * handle,UINT8 deviceNumber)
{
return ((PDP*)handle)-> SetDeviceNumber(deviceNumber);
}
}