#include "ctre/PDP.h" #include "FRC_NetworkCommunication/CANSessionMux.h" //CAN Comm #include // memset #include // usleep #define STATUS_1 0x8041400 #define STATUS_2 0x8041440 #define STATUS_3 0x8041480 #define STATUS_ENERGY 0x8041740 #define CONTROL_1 0x08041C00 /* PDP_Control_ClearStats */ #define EXPECTED_RESPONSE_TIMEOUT_MS (50) #define GET_STATUS1() CtreCanNode::recMsg rx = GetRx(STATUS_1|GetDeviceNumber(),EXPECTED_RESPONSE_TIMEOUT_MS) #define GET_STATUS2() CtreCanNode::recMsg rx = GetRx(STATUS_2|GetDeviceNumber(),EXPECTED_RESPONSE_TIMEOUT_MS) #define GET_STATUS3() CtreCanNode::recMsg rx = GetRx(STATUS_3|GetDeviceNumber(),EXPECTED_RESPONSE_TIMEOUT_MS) #define GET_STATUS_ENERGY() CtreCanNode::recMsg rx = GetRx(STATUS_ENERGY|GetDeviceNumber(),EXPECTED_RESPONSE_TIMEOUT_MS) /* encoder/decoders */ typedef struct _PdpStatus1_t{ unsigned chan1_h8:8; unsigned chan2_h6:6; unsigned chan1_l2:2; unsigned chan3_h4:4; unsigned chan2_l4:4; unsigned chan4_h2:2; unsigned chan3_l6:6; unsigned chan4_l8:8; unsigned chan5_h8:8; unsigned chan6_h6:6; unsigned chan5_l2:2; unsigned reserved4:4; unsigned chan6_l4:4; }PdpStatus1_t; typedef struct _PdpStatus2_t{ unsigned chan7_h8:8; unsigned chan8_h6:6; unsigned chan7_l2:2; unsigned chan9_h4:4; unsigned chan8_l4:4; unsigned chan10_h2:2; unsigned chan9_l6:6; unsigned chan10_l8:8; unsigned chan11_h8:8; unsigned chan12_h6:6; unsigned chan11_l2:2; unsigned reserved4:4; unsigned chan12_l4:4; }PdpStatus2_t; typedef struct _PdpStatus3_t{ unsigned chan13_h8:8; unsigned chan14_h6:6; unsigned chan13_l2:2; unsigned chan15_h4:4; unsigned chan14_l4:4; unsigned chan16_h2:2; unsigned chan15_l6:6; unsigned chan16_l8:8; unsigned internalResBattery_mOhms:8; unsigned busVoltage:8; unsigned temp:8; }PdpStatus3_t; typedef struct _PDP_Status_Energy_t { unsigned TmeasMs_likelywillbe20ms_:8; unsigned TotalCurrent_125mAperunit_h8:8; unsigned Power_125mWperunit_h4:4; unsigned TotalCurrent_125mAperunit_l4:4; unsigned Power_125mWperunit_m8:8; unsigned Energy_125mWPerUnitXTmeas_h4:4; unsigned Power_125mWperunit_l4:4; unsigned Energy_125mWPerUnitXTmeas_mh8:8; unsigned Energy_125mWPerUnitXTmeas_ml8:8; unsigned Energy_125mWPerUnitXTmeas_l8:8; } PDP_Status_Energy_t ; PDP::PDP(UINT8 deviceNumber): CtreCanNode(deviceNumber) { RegisterRx(STATUS_1 | deviceNumber ); RegisterRx(STATUS_2 | deviceNumber ); RegisterRx(STATUS_3 | deviceNumber ); } /* PDP D'tor */ PDP::~PDP() { } CTR_Code PDP::GetChannelCurrent(UINT8 idx, double ¤t) { CTR_Code retval = CTR_InvalidParamValue; uint32_t raw = 0; if(idx <= 5){ GET_STATUS1(); retval = rx.err; switch(idx){ case 0: raw = ((uint32_t)rx->chan1_h8 << 2) | rx->chan1_l2; break; case 1: raw = ((uint32_t)rx->chan2_h6 << 4) | rx->chan2_l4; break; case 2: raw = ((uint32_t)rx->chan3_h4 << 6) | rx->chan3_l6; break; case 3: raw = ((uint32_t)rx->chan4_h2 << 8) | rx->chan4_l8; break; case 4: raw = ((uint32_t)rx->chan5_h8 << 2) | rx->chan5_l2; break; case 5: raw = ((uint32_t)rx->chan6_h6 << 4) | rx->chan6_l4; break; default: retval = CTR_InvalidParamValue; break; } }else if(idx <= 11){ GET_STATUS2(); retval = rx.err; switch(idx){ case 6: raw = ((uint32_t)rx->chan7_h8 << 2) | rx->chan7_l2; break; case 7: raw = ((uint32_t)rx->chan8_h6 << 4) | rx->chan8_l4; break; case 8: raw = ((uint32_t)rx->chan9_h4 << 6) | rx->chan9_l6; break; case 9: raw = ((uint32_t)rx->chan10_h2 << 8) | rx->chan10_l8; break; case 10: raw = ((uint32_t)rx->chan11_h8 << 2) | rx->chan11_l2; break; case 11: raw = ((uint32_t)rx->chan12_h6 << 4) | rx->chan12_l4; break; default: retval = CTR_InvalidParamValue; break; } }else if(idx <= 15){ GET_STATUS3(); retval = rx.err; switch(idx){ case 12: raw = ((uint32_t)rx->chan13_h8 << 2) | rx->chan13_l2; break; case 13: raw = ((uint32_t)rx->chan14_h6 << 4) | rx->chan14_l4; break; case 14: raw = ((uint32_t)rx->chan15_h4 << 6) | rx->chan15_l6; break; case 15: raw = ((uint32_t)rx->chan16_h2 << 8) | rx->chan16_l8; break; default: retval = CTR_InvalidParamValue; break; } } /* convert to amps */ current = (double)raw * 0.125; /* 7.3 fixed pt value in Amps */ /* signal caller with success */ return retval; } CTR_Code PDP::GetVoltage(double &voltage) { GET_STATUS3(); uint32_t raw = rx->busVoltage; voltage = (double)raw * 0.05 + 4.0; /* 50mV per unit plus 4V. */; return rx.err; } CTR_Code PDP::GetTemperature(double &tempC) { GET_STATUS3(); uint32_t raw = rx->temp; tempC = (double)raw * 1.03250836957542 - 67.8564500484966; return rx.err; } CTR_Code PDP::GetTotalCurrent(double ¤tAmps) { GET_STATUS_ENERGY(); uint32_t raw; raw = rx->TotalCurrent_125mAperunit_h8; raw <<= 4; raw |= rx->TotalCurrent_125mAperunit_l4; currentAmps = 0.125 * raw; return rx.err; } CTR_Code PDP::GetTotalPower(double &powerWatts) { GET_STATUS_ENERGY(); uint32_t raw; raw = rx->Power_125mWperunit_h4; raw <<= 8; raw |= rx->Power_125mWperunit_m8; raw <<= 4; raw |= rx->Power_125mWperunit_l4; powerWatts = 0.125 * raw; return rx.err; } CTR_Code PDP::GetTotalEnergy(double &energyJoules) { GET_STATUS_ENERGY(); uint32_t raw; raw = rx->Energy_125mWPerUnitXTmeas_h4; raw <<= 8; raw |= rx->Energy_125mWPerUnitXTmeas_mh8; raw <<= 8; raw |= rx->Energy_125mWPerUnitXTmeas_ml8; raw <<= 8; raw |= rx->Energy_125mWPerUnitXTmeas_l8; energyJoules = 0.125 * raw; /* mW integrated every TmeasMs */ energyJoules *= 0.001; /* convert from mW to W */ energyJoules *= rx->TmeasMs_likelywillbe20ms_; /* multiplied by TmeasMs = joules */ return rx.err; } /* Clear sticky faults. * @Return - CTR_Code - Error code (if any) */ CTR_Code PDP::ClearStickyFaults() { int32_t status = 0; uint8_t pdpControl[] = { 0x80 }; /* only bit set is ClearStickyFaults */ FRC_NetworkCommunication_CANSessionMux_sendMessage(CONTROL_1 | GetDeviceNumber(), pdpControl, sizeof(pdpControl), 0, &status); if(status) return CTR_TxFailed; return CTR_OKAY; } /* Reset Energy Signals * @Return - CTR_Code - Error code (if any) */ CTR_Code PDP::ResetEnergy() { int32_t status = 0; uint8_t pdpControl[] = { 0x40 }; /* only bit set is ResetEnergy */ FRC_NetworkCommunication_CANSessionMux_sendMessage(CONTROL_1 | GetDeviceNumber(), pdpControl, sizeof(pdpControl), 0, &status); if(status) return CTR_TxFailed; return CTR_OKAY; } //------------------ 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) { } }