mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-29 02:21:44 +00:00
[hal, wpilib] Rewrite CAN APIs (#7798)
This commit is contained in:
@@ -15,12 +15,13 @@
|
||||
|
||||
using namespace frc;
|
||||
|
||||
CAN::CAN(int deviceId) : CAN{kTeamManufacturer, deviceId, kTeamDeviceType} {}
|
||||
CAN::CAN(int busId, int deviceId)
|
||||
: CAN{busId, deviceId, kTeamManufacturer, kTeamDeviceType} {}
|
||||
|
||||
CAN::CAN(int deviceId, int deviceManufacturer, int deviceType) {
|
||||
CAN::CAN(int busId, int deviceId, int deviceManufacturer, int deviceType) {
|
||||
int32_t status = 0;
|
||||
m_handle = HAL_InitializeCAN(
|
||||
static_cast<HAL_CANManufacturer>(deviceManufacturer), deviceId,
|
||||
busId, static_cast<HAL_CANManufacturer>(deviceManufacturer), deviceId,
|
||||
static_cast<HAL_CANDeviceType>(deviceType), &status);
|
||||
FRC_CheckErrorStatus(status, "device id {} mfg {} type {}", deviceId,
|
||||
deviceManufacturer, deviceType);
|
||||
@@ -30,41 +31,41 @@ CAN::CAN(int deviceId, int deviceManufacturer, int deviceType) {
|
||||
"");
|
||||
}
|
||||
|
||||
void CAN::WritePacket(const uint8_t* data, int length, int apiId) {
|
||||
void CAN::WritePacket(int apiId, const HAL_CANMessage& message) {
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacket(m_handle, data, length, apiId, &status);
|
||||
HAL_WriteCANPacket(m_handle, apiId, &message, &status);
|
||||
FRC_CheckErrorStatus(status, "WritePacket");
|
||||
}
|
||||
|
||||
void CAN::WritePacketRepeating(const uint8_t* data, int length, int apiId,
|
||||
void CAN::WritePacketRepeating(int apiId, const HAL_CANMessage& message,
|
||||
int repeatMs) {
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacketRepeating(m_handle, data, length, apiId, repeatMs, &status);
|
||||
HAL_WriteCANPacketRepeating(m_handle, apiId, &message, repeatMs, &status);
|
||||
FRC_CheckErrorStatus(status, "WritePacketRepeating");
|
||||
}
|
||||
|
||||
void CAN::WriteRTRFrame(int length, int apiId) {
|
||||
void CAN::WriteRTRFrame(int apiId, const HAL_CANMessage& message) {
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANRTRFrame(m_handle, length, apiId, &status);
|
||||
HAL_WriteCANRTRFrame(m_handle, apiId, &message, &status);
|
||||
FRC_CheckErrorStatus(status, "WriteRTRFrame");
|
||||
}
|
||||
|
||||
int CAN::WritePacketNoError(const uint8_t* data, int length, int apiId) {
|
||||
int CAN::WritePacketNoError(int apiId, const HAL_CANMessage& message) {
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacket(m_handle, data, length, apiId, &status);
|
||||
HAL_WriteCANPacket(m_handle, apiId, &message, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
int CAN::WritePacketRepeatingNoError(const uint8_t* data, int length, int apiId,
|
||||
int CAN::WritePacketRepeatingNoError(int apiId, const HAL_CANMessage& message,
|
||||
int repeatMs) {
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacketRepeating(m_handle, data, length, apiId, repeatMs, &status);
|
||||
HAL_WriteCANPacketRepeating(m_handle, apiId, &message, repeatMs, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
int CAN::WriteRTRFrameNoError(int length, int apiId) {
|
||||
int CAN::WriteRTRFrameNoError(int apiId, const HAL_CANMessage& message) {
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANRTRFrame(m_handle, length, apiId, &status);
|
||||
HAL_WriteCANRTRFrame(m_handle, apiId, &message, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -74,10 +75,9 @@ void CAN::StopPacketRepeating(int apiId) {
|
||||
FRC_CheckErrorStatus(status, "StopPacketRepeating");
|
||||
}
|
||||
|
||||
bool CAN::ReadPacketNew(int apiId, CANData* data) {
|
||||
bool CAN::ReadPacketNew(int apiId, HAL_CANReceiveMessage* data) {
|
||||
int32_t status = 0;
|
||||
HAL_ReadCANPacketNew(m_handle, apiId, data->data, &data->length,
|
||||
&data->timestamp, &status);
|
||||
HAL_ReadCANPacketNew(m_handle, apiId, data, &status);
|
||||
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
|
||||
return false;
|
||||
}
|
||||
@@ -89,10 +89,9 @@ bool CAN::ReadPacketNew(int apiId, CANData* data) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CAN::ReadPacketLatest(int apiId, CANData* data) {
|
||||
bool CAN::ReadPacketLatest(int apiId, HAL_CANReceiveMessage* data) {
|
||||
int32_t status = 0;
|
||||
HAL_ReadCANPacketLatest(m_handle, apiId, data->data, &data->length,
|
||||
&data->timestamp, &status);
|
||||
HAL_ReadCANPacketLatest(m_handle, apiId, data, &status);
|
||||
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
|
||||
return false;
|
||||
}
|
||||
@@ -104,10 +103,10 @@ bool CAN::ReadPacketLatest(int apiId, CANData* data) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CAN::ReadPacketTimeout(int apiId, int timeoutMs, CANData* data) {
|
||||
bool CAN::ReadPacketTimeout(int apiId, int timeoutMs,
|
||||
HAL_CANReceiveMessage* data) {
|
||||
int32_t status = 0;
|
||||
HAL_ReadCANPacketTimeout(m_handle, apiId, data->data, &data->length,
|
||||
&data->timestamp, timeoutMs, &status);
|
||||
HAL_ReadCANPacketTimeout(m_handle, apiId, data, timeoutMs, &status);
|
||||
if (status == HAL_CAN_TIMEOUT ||
|
||||
status == HAL_ERR_CANSessionMux_MessageNotFound) {
|
||||
return false;
|
||||
@@ -119,7 +118,3 @@ bool CAN::ReadPacketTimeout(int apiId, int timeoutMs, CANData* data) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t CAN::GetTimestampBaseTime() {
|
||||
return HAL_GetCANPacketBaseTime();
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
using namespace frc;
|
||||
|
||||
Compressor::Compressor(int module, PneumaticsModuleType moduleType)
|
||||
: m_module{PneumaticsBase::GetForType(module, moduleType)},
|
||||
Compressor::Compressor(int busId, int module, PneumaticsModuleType moduleType)
|
||||
: m_module{PneumaticsBase::GetForType(busId, module, moduleType)},
|
||||
m_moduleType{moduleType} {
|
||||
if (!m_module->ReserveCompressor()) {
|
||||
throw FRC_MakeError(err::ResourceAlreadyAllocated, "{}", module);
|
||||
@@ -27,8 +27,9 @@ Compressor::Compressor(int module, PneumaticsModuleType moduleType)
|
||||
wpi::SendableRegistry::Add(this, "Compressor", module);
|
||||
}
|
||||
|
||||
Compressor::Compressor(PneumaticsModuleType moduleType)
|
||||
: Compressor{PneumaticsBase::GetDefaultForType(moduleType), moduleType} {}
|
||||
Compressor::Compressor(int busId, PneumaticsModuleType moduleType)
|
||||
: Compressor{busId, PneumaticsBase::GetDefaultForType(moduleType),
|
||||
moduleType} {}
|
||||
|
||||
Compressor::~Compressor() {
|
||||
if (m_module) {
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
|
||||
using namespace frc;
|
||||
|
||||
DoubleSolenoid::DoubleSolenoid(int module, PneumaticsModuleType moduleType,
|
||||
DoubleSolenoid::DoubleSolenoid(int busId, int module,
|
||||
PneumaticsModuleType moduleType,
|
||||
int forwardChannel, int reverseChannel)
|
||||
: m_module{PneumaticsBase::GetForType(module, moduleType)},
|
||||
: m_module{PneumaticsBase::GetForType(busId, module, moduleType)},
|
||||
m_forwardChannel{forwardChannel},
|
||||
m_reverseChannel{reverseChannel} {
|
||||
if (!m_module->CheckSolenoidChannel(m_forwardChannel)) {
|
||||
@@ -56,10 +57,10 @@ DoubleSolenoid::DoubleSolenoid(int module, PneumaticsModuleType moduleType,
|
||||
m_module->GetModuleNumber(), m_forwardChannel);
|
||||
}
|
||||
|
||||
DoubleSolenoid::DoubleSolenoid(PneumaticsModuleType moduleType,
|
||||
DoubleSolenoid::DoubleSolenoid(int busId, PneumaticsModuleType moduleType,
|
||||
int forwardChannel, int reverseChannel)
|
||||
: DoubleSolenoid{PneumaticsBase::GetDefaultForType(moduleType), moduleType,
|
||||
forwardChannel, reverseChannel} {}
|
||||
: DoubleSolenoid{busId, PneumaticsBase::GetDefaultForType(moduleType),
|
||||
moduleType, forwardChannel, reverseChannel} {}
|
||||
|
||||
DoubleSolenoid::~DoubleSolenoid() {
|
||||
if (m_module) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <string>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <hal/Ports.h>
|
||||
#include <hal/REVPH.h>
|
||||
#include <hal/UsageReporting.h>
|
||||
#include <wpi/NullDeleter.h>
|
||||
@@ -39,26 +40,31 @@ units::volt_t PSIToVolts(units::pounds_per_square_inch_t pressure,
|
||||
}
|
||||
|
||||
wpi::mutex PneumaticHub::m_handleLock;
|
||||
std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>>
|
||||
PneumaticHub::m_handleMap = nullptr;
|
||||
std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>[]>
|
||||
PneumaticHub::m_handleMaps = nullptr;
|
||||
|
||||
// Always called under lock, so we can avoid the double lock from the magic
|
||||
// static
|
||||
std::weak_ptr<PneumaticHub::DataStore>& PneumaticHub::GetDataStore(int module) {
|
||||
if (!m_handleMap) {
|
||||
m_handleMap = std::make_unique<
|
||||
wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>>();
|
||||
std::weak_ptr<PneumaticHub::DataStore>& PneumaticHub::GetDataStore(int busId,
|
||||
int module) {
|
||||
int32_t numBuses = HAL_GetNumCanBuses();
|
||||
FRC_AssertMessage(busId >= 0 && busId < numBuses,
|
||||
"Bus {} out of range. Must be [0-{}).", busId, numBuses);
|
||||
if (!m_handleMaps) {
|
||||
m_handleMaps = std::make_unique<
|
||||
wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>[]>(numBuses);
|
||||
}
|
||||
return (*m_handleMap)[module];
|
||||
return m_handleMaps[busId][module];
|
||||
}
|
||||
|
||||
class PneumaticHub::DataStore {
|
||||
public:
|
||||
explicit DataStore(int module, const char* stackTrace) {
|
||||
explicit DataStore(int busId, int module, const char* stackTrace) {
|
||||
int32_t status = 0;
|
||||
HAL_REVPHHandle handle = HAL_InitializeREVPH(module, stackTrace, &status);
|
||||
HAL_REVPHHandle handle =
|
||||
HAL_InitializeREVPH(busId, module, stackTrace, &status);
|
||||
FRC_CheckErrorStatus(status, "Module {}", module);
|
||||
m_moduleObject = PneumaticHub{handle, module};
|
||||
m_moduleObject = PneumaticHub{busId, handle, module};
|
||||
m_moduleObject.m_dataStore =
|
||||
std::shared_ptr<DataStore>{this, wpi::NullDeleter<DataStore>()};
|
||||
|
||||
@@ -105,27 +111,28 @@ class PneumaticHub::DataStore {
|
||||
uint32_t m_reservedMask{0};
|
||||
bool m_compressorReserved{false};
|
||||
wpi::mutex m_reservedLock;
|
||||
PneumaticHub m_moduleObject{HAL_kInvalidHandle, 0};
|
||||
PneumaticHub m_moduleObject{0, HAL_kInvalidHandle, 0};
|
||||
std::array<units::millisecond_t, 16> m_oneShotDurMs{0_ms};
|
||||
};
|
||||
|
||||
PneumaticHub::PneumaticHub()
|
||||
: PneumaticHub{SensorUtil::GetDefaultREVPHModule()} {}
|
||||
PneumaticHub::PneumaticHub(int busId)
|
||||
: PneumaticHub{busId, SensorUtil::GetDefaultREVPHModule()} {}
|
||||
|
||||
PneumaticHub::PneumaticHub(int module) {
|
||||
PneumaticHub::PneumaticHub(int busId, int module) {
|
||||
std::string stackTrace = wpi::GetStackTrace(1);
|
||||
std::scoped_lock lock(m_handleLock);
|
||||
auto& res = GetDataStore(module);
|
||||
auto& res = GetDataStore(busId, module);
|
||||
m_dataStore = res.lock();
|
||||
if (!m_dataStore) {
|
||||
m_dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
|
||||
m_dataStore =
|
||||
std::make_shared<DataStore>(busId, module, stackTrace.c_str());
|
||||
res = m_dataStore;
|
||||
}
|
||||
m_handle = m_dataStore->m_moduleObject.m_handle;
|
||||
m_module = module;
|
||||
}
|
||||
|
||||
PneumaticHub::PneumaticHub(HAL_REVPHHandle handle, int module)
|
||||
PneumaticHub::PneumaticHub(int /* busId */, HAL_REVPHHandle handle, int module)
|
||||
: m_handle{handle}, m_module{module} {}
|
||||
|
||||
bool PneumaticHub::GetCompressor() const {
|
||||
@@ -446,13 +453,14 @@ void PneumaticHub::ReportUsage(std::string_view device, std::string_view data) {
|
||||
HAL_ReportUsage(fmt::format("PH[{}]/{}", m_module, device), data);
|
||||
}
|
||||
|
||||
std::shared_ptr<PneumaticsBase> PneumaticHub::GetForModule(int module) {
|
||||
std::shared_ptr<PneumaticsBase> PneumaticHub::GetForModule(int busId,
|
||||
int module) {
|
||||
std::string stackTrace = wpi::GetStackTrace(1);
|
||||
std::scoped_lock lock(m_handleLock);
|
||||
auto& res = GetDataStore(module);
|
||||
auto& res = GetDataStore(busId, module);
|
||||
std::shared_ptr<DataStore> dataStore = res.lock();
|
||||
if (!dataStore) {
|
||||
dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
|
||||
dataStore = std::make_shared<DataStore>(busId, module, stackTrace.c_str());
|
||||
res = dataStore;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ static_assert(
|
||||
HAL_REVPHCompressorConfigType::HAL_REVPHCompressorConfigType_kHybrid);
|
||||
|
||||
std::shared_ptr<PneumaticsBase> PneumaticsBase::GetForType(
|
||||
int module, PneumaticsModuleType moduleType) {
|
||||
int busId, int module, PneumaticsModuleType moduleType) {
|
||||
if (moduleType == PneumaticsModuleType::CTREPCM) {
|
||||
return PneumaticsControlModule::GetForModule(module);
|
||||
return PneumaticsControlModule::GetForModule(busId, module);
|
||||
} else if (moduleType == PneumaticsModuleType::REVPH) {
|
||||
return PneumaticHub::GetForModule(module);
|
||||
return PneumaticHub::GetForModule(busId, module);
|
||||
}
|
||||
throw FRC_MakeError(err::InvalidParameter, "{}",
|
||||
static_cast<int>(moduleType));
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <hal/CTREPCM.h>
|
||||
#include <hal/Ports.h>
|
||||
#include <hal/UsageReporting.h>
|
||||
#include <wpi/NullDeleter.h>
|
||||
#include <wpi/StackTrace.h>
|
||||
@@ -23,28 +24,32 @@ using namespace frc;
|
||||
|
||||
wpi::mutex PneumaticsControlModule::m_handleLock;
|
||||
std::unique_ptr<
|
||||
wpi::DenseMap<int, std::weak_ptr<PneumaticsControlModule::DataStore>>>
|
||||
PneumaticsControlModule::m_handleMap = nullptr;
|
||||
wpi::DenseMap<int, std::weak_ptr<PneumaticsControlModule::DataStore>>[]>
|
||||
PneumaticsControlModule::m_handleMaps = nullptr;
|
||||
|
||||
// Always called under lock, so we can avoid the double lock from the magic
|
||||
// static
|
||||
std::weak_ptr<PneumaticsControlModule::DataStore>&
|
||||
PneumaticsControlModule::GetDataStore(int module) {
|
||||
if (!m_handleMap) {
|
||||
m_handleMap = std::make_unique<wpi::DenseMap<
|
||||
int, std::weak_ptr<PneumaticsControlModule::DataStore>>>();
|
||||
PneumaticsControlModule::GetDataStore(int busId, int module) {
|
||||
int32_t numBuses = HAL_GetNumCanBuses();
|
||||
FRC_AssertMessage(busId >= 0 && busId < numBuses,
|
||||
"Bus {} out of range. Must be [0-{}).", busId, numBuses);
|
||||
if (!m_handleMaps) {
|
||||
m_handleMaps = std::make_unique<wpi::DenseMap<
|
||||
int, std::weak_ptr<PneumaticsControlModule::DataStore>>[]>(numBuses);
|
||||
}
|
||||
return (*m_handleMap)[module];
|
||||
|
||||
return m_handleMaps[busId][module];
|
||||
}
|
||||
|
||||
class PneumaticsControlModule::DataStore {
|
||||
public:
|
||||
explicit DataStore(int module, const char* stackTrace) {
|
||||
explicit DataStore(int busId, int module, const char* stackTrace) {
|
||||
int32_t status = 0;
|
||||
HAL_CTREPCMHandle handle =
|
||||
HAL_InitializeCTREPCM(module, stackTrace, &status);
|
||||
HAL_InitializeCTREPCM(busId, module, stackTrace, &status);
|
||||
FRC_CheckErrorStatus(status, "Module {}", module);
|
||||
m_moduleObject = PneumaticsControlModule{handle, module};
|
||||
m_moduleObject = PneumaticsControlModule{busId, handle, module};
|
||||
m_moduleObject.m_dataStore =
|
||||
std::shared_ptr<DataStore>{this, wpi::NullDeleter<DataStore>()};
|
||||
}
|
||||
@@ -59,26 +64,28 @@ class PneumaticsControlModule::DataStore {
|
||||
uint32_t m_reservedMask{0};
|
||||
bool m_compressorReserved{false};
|
||||
wpi::mutex m_reservedLock;
|
||||
PneumaticsControlModule m_moduleObject{HAL_kInvalidHandle, 0};
|
||||
PneumaticsControlModule m_moduleObject{0, HAL_kInvalidHandle, 0};
|
||||
};
|
||||
|
||||
PneumaticsControlModule::PneumaticsControlModule()
|
||||
: PneumaticsControlModule{SensorUtil::GetDefaultCTREPCMModule()} {}
|
||||
PneumaticsControlModule::PneumaticsControlModule(int busId)
|
||||
: PneumaticsControlModule{busId, SensorUtil::GetDefaultCTREPCMModule()} {}
|
||||
|
||||
PneumaticsControlModule::PneumaticsControlModule(int module) {
|
||||
PneumaticsControlModule::PneumaticsControlModule(int busId, int module) {
|
||||
std::string stackTrace = wpi::GetStackTrace(1);
|
||||
std::scoped_lock lock(m_handleLock);
|
||||
auto& res = GetDataStore(module);
|
||||
auto& res = GetDataStore(busId, module);
|
||||
m_dataStore = res.lock();
|
||||
if (!m_dataStore) {
|
||||
m_dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
|
||||
m_dataStore =
|
||||
std::make_shared<DataStore>(busId, module, stackTrace.c_str());
|
||||
res = m_dataStore;
|
||||
}
|
||||
m_handle = m_dataStore->m_moduleObject.m_handle;
|
||||
m_module = module;
|
||||
}
|
||||
|
||||
PneumaticsControlModule::PneumaticsControlModule(HAL_CTREPCMHandle handle,
|
||||
PneumaticsControlModule::PneumaticsControlModule(int /* busId */,
|
||||
HAL_CTREPCMHandle handle,
|
||||
int module)
|
||||
: m_handle{handle}, m_module{module} {}
|
||||
|
||||
@@ -297,13 +304,13 @@ void PneumaticsControlModule::ReportUsage(std::string_view device,
|
||||
}
|
||||
|
||||
std::shared_ptr<PneumaticsBase> PneumaticsControlModule::GetForModule(
|
||||
int module) {
|
||||
int busId, int module) {
|
||||
std::string stackTrace = wpi::GetStackTrace(1);
|
||||
std::scoped_lock lock(m_handleLock);
|
||||
auto& res = GetDataStore(module);
|
||||
auto& res = GetDataStore(busId, module);
|
||||
std::shared_ptr<DataStore> dataStore = res.lock();
|
||||
if (!dataStore) {
|
||||
dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
|
||||
dataStore = std::make_shared<DataStore>(busId, module, stackTrace.c_str());
|
||||
res = dataStore;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,12 +27,12 @@ static_assert(frc::PowerDistribution::kDefaultModule ==
|
||||
|
||||
using namespace frc;
|
||||
|
||||
PowerDistribution::PowerDistribution() {
|
||||
PowerDistribution::PowerDistribution(int busId) {
|
||||
auto stack = wpi::GetStackTrace(1);
|
||||
|
||||
int32_t status = 0;
|
||||
m_handle = HAL_InitializePowerDistribution(
|
||||
kDefaultModule,
|
||||
busId, kDefaultModule,
|
||||
HAL_PowerDistributionType::HAL_PowerDistributionType_kAutomatic,
|
||||
stack.c_str(), &status);
|
||||
FRC_CheckErrorStatus(status, "Module {}", kDefaultModule);
|
||||
@@ -48,13 +48,14 @@ PowerDistribution::PowerDistribution() {
|
||||
wpi::SendableRegistry::Add(this, "PowerDistribution", m_module);
|
||||
}
|
||||
|
||||
PowerDistribution::PowerDistribution(int module, ModuleType moduleType) {
|
||||
PowerDistribution::PowerDistribution(int busId, int module,
|
||||
ModuleType moduleType) {
|
||||
auto stack = wpi::GetStackTrace(1);
|
||||
|
||||
int32_t status = 0;
|
||||
m_handle = HAL_InitializePowerDistribution(
|
||||
module, static_cast<HAL_PowerDistributionType>(moduleType), stack.c_str(),
|
||||
&status);
|
||||
busId, module, static_cast<HAL_PowerDistributionType>(moduleType),
|
||||
stack.c_str(), &status);
|
||||
FRC_CheckErrorStatus(status, "Module {}", module);
|
||||
m_module = HAL_GetPowerDistributionModuleNumber(m_handle, &status);
|
||||
FRC_ReportError(status, "Module {}", module);
|
||||
|
||||
@@ -284,15 +284,16 @@ RadioLEDState RobotController::GetRadioLEDState() {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
CANStatus RobotController::GetCANStatus() {
|
||||
CANStatus RobotController::GetCANStatus(int busId) {
|
||||
int32_t status = 0;
|
||||
float percentBusUtilization = 0;
|
||||
uint32_t busOffCount = 0;
|
||||
uint32_t txFullCount = 0;
|
||||
uint32_t receiveErrorCount = 0;
|
||||
uint32_t transmitErrorCount = 0;
|
||||
HAL_CAN_GetCANStatus(&percentBusUtilization, &busOffCount, &txFullCount,
|
||||
&receiveErrorCount, &transmitErrorCount, &status);
|
||||
HAL_CAN_GetCANStatus(busId, &percentBusUtilization, &busOffCount,
|
||||
&txFullCount, &receiveErrorCount, &transmitErrorCount,
|
||||
&status);
|
||||
FRC_CheckErrorStatus(status, "GetCANStatus");
|
||||
return {percentBusUtilization, static_cast<int>(busOffCount),
|
||||
static_cast<int>(txFullCount), static_cast<int>(receiveErrorCount),
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
|
||||
using namespace frc;
|
||||
|
||||
Solenoid::Solenoid(int module, PneumaticsModuleType moduleType, int channel)
|
||||
: m_module{PneumaticsBase::GetForType(module, moduleType)},
|
||||
Solenoid::Solenoid(int busId, int module, PneumaticsModuleType moduleType,
|
||||
int channel)
|
||||
: m_module{PneumaticsBase::GetForType(busId, module, moduleType)},
|
||||
m_channel{channel} {
|
||||
if (!m_module->CheckSolenoidChannel(m_channel)) {
|
||||
throw FRC_MakeError(err::ChannelIndexOutOfRange, "Channel {}", m_channel);
|
||||
@@ -32,8 +33,8 @@ Solenoid::Solenoid(int module, PneumaticsModuleType moduleType, int channel)
|
||||
m_channel);
|
||||
}
|
||||
|
||||
Solenoid::Solenoid(PneumaticsModuleType moduleType, int channel)
|
||||
: Solenoid{PneumaticsBase::GetDefaultForType(moduleType), moduleType,
|
||||
Solenoid::Solenoid(int busId, PneumaticsModuleType moduleType, int channel)
|
||||
: Solenoid{busId, PneumaticsBase::GetDefaultForType(moduleType), moduleType,
|
||||
channel} {}
|
||||
|
||||
Solenoid::~Solenoid() {
|
||||
|
||||
@@ -9,14 +9,6 @@
|
||||
#include <hal/CANAPI.h>
|
||||
|
||||
namespace frc {
|
||||
struct CANData {
|
||||
/** Contents of the CAN packet. */
|
||||
uint8_t data[8];
|
||||
/** Length of packet in bytes. */
|
||||
int32_t length;
|
||||
/** CAN frame timestamp in milliseconds. */
|
||||
uint64_t timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
* High level class for interfacing with CAN devices conforming to
|
||||
@@ -35,20 +27,22 @@ class CAN {
|
||||
* This uses the team manufacturer and device types.
|
||||
* The device ID is 6 bits (0-63)
|
||||
*
|
||||
* @param busId The bus id
|
||||
* @param deviceId The device id
|
||||
*/
|
||||
explicit CAN(int deviceId);
|
||||
CAN(int busId, int deviceId);
|
||||
|
||||
/**
|
||||
* Create a new CAN communication interface with a specific device ID,
|
||||
* manufacturer and device type. The device ID is 6 bits, the
|
||||
* manufacturer is 8 bits, and the device type is 5 bits.
|
||||
*
|
||||
* @param busId The bus id
|
||||
* @param deviceId The device ID
|
||||
* @param deviceManufacturer The device manufacturer
|
||||
* @param deviceType The device type
|
||||
*/
|
||||
CAN(int deviceId, int deviceManufacturer, int deviceType);
|
||||
CAN(int busId, int deviceId, int deviceManufacturer, int deviceType);
|
||||
|
||||
CAN(CAN&&) = default;
|
||||
CAN& operator=(CAN&&) = default;
|
||||
@@ -56,23 +50,21 @@ class CAN {
|
||||
/**
|
||||
* Write a packet to the CAN device with a specific ID. This ID is 10 bits.
|
||||
*
|
||||
* @param data The data to write (8 bytes max)
|
||||
* @param length The data length to write
|
||||
* @param apiId The API ID to write.
|
||||
* @param message the CAN message.
|
||||
*/
|
||||
void WritePacket(const uint8_t* data, int length, int apiId);
|
||||
void WritePacket(int apiId, const HAL_CANMessage& message);
|
||||
|
||||
/**
|
||||
* Write a repeating packet to the CAN device with a specific ID. This ID is
|
||||
* 10 bits. The RoboRIO will automatically repeat the packet at the specified
|
||||
* interval
|
||||
*
|
||||
* @param data The data to write (8 bytes max)
|
||||
* @param length The data length to write
|
||||
* @param apiId The API ID to write.
|
||||
* @param message the CAN message.
|
||||
* @param repeatMs The period to repeat the packet at.
|
||||
*/
|
||||
void WritePacketRepeating(const uint8_t* data, int length, int apiId,
|
||||
void WritePacketRepeating(int apiId, const HAL_CANMessage& message,
|
||||
int repeatMs);
|
||||
|
||||
/**
|
||||
@@ -80,31 +72,29 @@ class CAN {
|
||||
* bits. The length by spec must match what is returned by the responding
|
||||
* device
|
||||
*
|
||||
* @param length The length to request (0 to 8)
|
||||
* @param apiId The API ID to write.
|
||||
* @param message the CAN message.
|
||||
*/
|
||||
void WriteRTRFrame(int length, int apiId);
|
||||
void WriteRTRFrame(int apiId, const HAL_CANMessage& message);
|
||||
|
||||
/**
|
||||
* Write a packet to the CAN device with a specific ID. This ID is 10 bits.
|
||||
*
|
||||
* @param data The data to write (8 bytes max)
|
||||
* @param length The data length to write
|
||||
* @param apiId The API ID to write.
|
||||
* @param message the CAN message.
|
||||
*/
|
||||
int WritePacketNoError(const uint8_t* data, int length, int apiId);
|
||||
int WritePacketNoError(int apiId, const HAL_CANMessage& message);
|
||||
|
||||
/**
|
||||
* Write a repeating packet to the CAN device with a specific ID. This ID is
|
||||
* 10 bits. The RoboRIO will automatically repeat the packet at the specified
|
||||
* interval
|
||||
*
|
||||
* @param data The data to write (8 bytes max)
|
||||
* @param length The data length to write
|
||||
* @param apiId The API ID to write.
|
||||
* @param message the CAN message.
|
||||
* @param repeatMs The period to repeat the packet at.
|
||||
*/
|
||||
int WritePacketRepeatingNoError(const uint8_t* data, int length, int apiId,
|
||||
int WritePacketRepeatingNoError(int apiId, const HAL_CANMessage& message,
|
||||
int repeatMs);
|
||||
|
||||
/**
|
||||
@@ -112,10 +102,10 @@ class CAN {
|
||||
* bits. The length by spec must match what is returned by the responding
|
||||
* device
|
||||
*
|
||||
* @param length The length to request (0 to 8)
|
||||
* @param apiId The API ID to write.
|
||||
* @param message the CAN message.
|
||||
*/
|
||||
int WriteRTRFrameNoError(int length, int apiId);
|
||||
int WriteRTRFrameNoError(int apiId, const HAL_CANMessage& message);
|
||||
|
||||
/**
|
||||
* Stop a repeating packet with a specific ID. This ID is 10 bits.
|
||||
@@ -133,7 +123,7 @@ class CAN {
|
||||
* @param data Storage for the received data.
|
||||
* @return True if the data is valid, otherwise false.
|
||||
*/
|
||||
bool ReadPacketNew(int apiId, CANData* data);
|
||||
bool ReadPacketNew(int apiId, HAL_CANReceiveMessage* data);
|
||||
|
||||
/**
|
||||
* Read a CAN packet. The will continuously return the last packet received,
|
||||
@@ -143,7 +133,7 @@ class CAN {
|
||||
* @param data Storage for the received data.
|
||||
* @return True if the data is valid, otherwise false.
|
||||
*/
|
||||
bool ReadPacketLatest(int apiId, CANData* data);
|
||||
bool ReadPacketLatest(int apiId, HAL_CANReceiveMessage* data);
|
||||
|
||||
/**
|
||||
* Read a CAN packet. The will return the last packet received until the
|
||||
@@ -154,16 +144,7 @@ class CAN {
|
||||
* @param data Storage for the received data.
|
||||
* @return True if the data is valid, otherwise false.
|
||||
*/
|
||||
bool ReadPacketTimeout(int apiId, int timeoutMs, CANData* data);
|
||||
|
||||
/**
|
||||
* Reads the current value of the millisecond-resolution timer that CANData
|
||||
* timestamps are based on
|
||||
*
|
||||
* @return Current value of timer used as a base time for CANData timestamps
|
||||
* in milliseconds
|
||||
*/
|
||||
static uint64_t GetTimestampBaseTime();
|
||||
bool ReadPacketTimeout(int apiId, int timeoutMs, HAL_CANReceiveMessage* data);
|
||||
|
||||
/// Team manufacturer.
|
||||
static constexpr HAL_CANManufacturer kTeamManufacturer = HAL_CAN_Man_kTeamUse;
|
||||
|
||||
@@ -37,17 +37,19 @@ class Compressor : public wpi::Sendable,
|
||||
/**
|
||||
* Constructs a compressor for a specified module and type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module The module ID to use.
|
||||
* @param moduleType The module type to use.
|
||||
*/
|
||||
Compressor(int module, PneumaticsModuleType moduleType);
|
||||
Compressor(int busId, int module, PneumaticsModuleType moduleType);
|
||||
|
||||
/**
|
||||
* Constructs a compressor for a default module and specified type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param moduleType The module type to use.
|
||||
*/
|
||||
explicit Compressor(PneumaticsModuleType moduleType);
|
||||
Compressor(int busId, PneumaticsModuleType moduleType);
|
||||
|
||||
~Compressor() override;
|
||||
|
||||
|
||||
@@ -41,23 +41,25 @@ class DoubleSolenoid : public wpi::Sendable,
|
||||
* Constructs a double solenoid for a specified module of a specific module
|
||||
* type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module The module of the solenoid module to use.
|
||||
* @param moduleType The module type to use.
|
||||
* @param forwardChannel The forward channel on the module to control.
|
||||
* @param reverseChannel The reverse channel on the module to control.
|
||||
*/
|
||||
DoubleSolenoid(int module, PneumaticsModuleType moduleType,
|
||||
DoubleSolenoid(int busId, int module, PneumaticsModuleType moduleType,
|
||||
int forwardChannel, int reverseChannel);
|
||||
|
||||
/**
|
||||
* Constructs a double solenoid for a default module of a specific module
|
||||
* type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param moduleType The module type to use.
|
||||
* @param forwardChannel The forward channel on the module to control.
|
||||
* @param reverseChannel The reverse channel on the module to control.
|
||||
*/
|
||||
DoubleSolenoid(PneumaticsModuleType moduleType, int forwardChannel,
|
||||
DoubleSolenoid(int busId, PneumaticsModuleType moduleType, int forwardChannel,
|
||||
int reverseChannel);
|
||||
|
||||
~DoubleSolenoid() override;
|
||||
|
||||
@@ -17,15 +17,20 @@ namespace frc {
|
||||
/** Module class for controlling a REV Robotics Pneumatic Hub. */
|
||||
class PneumaticHub : public PneumaticsBase {
|
||||
public:
|
||||
/** Constructs a PneumaticHub with the default ID (1). */
|
||||
PneumaticHub();
|
||||
/**
|
||||
* Constructs a PneumaticHub with the default ID (1).
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
*/
|
||||
explicit PneumaticHub(int busId);
|
||||
|
||||
/**
|
||||
* Constructs a PneumaticHub.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module module number to construct
|
||||
*/
|
||||
explicit PneumaticHub(int module);
|
||||
PneumaticHub(int busId, int module);
|
||||
|
||||
~PneumaticHub() override = default;
|
||||
|
||||
@@ -296,17 +301,17 @@ class PneumaticHub : public PneumaticsBase {
|
||||
class DataStore;
|
||||
friend class DataStore;
|
||||
friend class PneumaticsBase;
|
||||
PneumaticHub(HAL_REVPHHandle handle, int module);
|
||||
PneumaticHub(int busId, HAL_REVPHHandle handle, int module);
|
||||
|
||||
static std::shared_ptr<PneumaticsBase> GetForModule(int module);
|
||||
static std::shared_ptr<PneumaticsBase> GetForModule(int busId, int module);
|
||||
|
||||
std::shared_ptr<DataStore> m_dataStore;
|
||||
HAL_REVPHHandle m_handle;
|
||||
int m_module;
|
||||
|
||||
static wpi::mutex m_handleLock;
|
||||
static std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<DataStore>>>
|
||||
m_handleMap;
|
||||
static std::weak_ptr<DataStore>& GetDataStore(int module);
|
||||
static std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<DataStore>>[]>
|
||||
m_handleMaps;
|
||||
static std::weak_ptr<DataStore>& GetDataStore(int busId, int module);
|
||||
};
|
||||
} // namespace frc
|
||||
|
||||
@@ -267,12 +267,13 @@ class PneumaticsBase {
|
||||
/**
|
||||
* For internal use to get a module for a specific type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module module number
|
||||
* @param moduleType module type
|
||||
* @return module
|
||||
*/
|
||||
static std::shared_ptr<PneumaticsBase> GetForType(
|
||||
int module, PneumaticsModuleType moduleType);
|
||||
int busId, int module, PneumaticsModuleType moduleType);
|
||||
|
||||
/**
|
||||
* For internal use to get the default for a specific type.
|
||||
|
||||
@@ -17,15 +17,20 @@ namespace frc {
|
||||
* Module. */
|
||||
class PneumaticsControlModule : public PneumaticsBase {
|
||||
public:
|
||||
/** Constructs a PneumaticsControlModule with the default ID (0). */
|
||||
PneumaticsControlModule();
|
||||
/**
|
||||
* Constructs a PneumaticsControlModule with the default ID (0).
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
*/
|
||||
explicit PneumaticsControlModule(int busId);
|
||||
|
||||
/**
|
||||
* Constructs a PneumaticsControlModule.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module module number to construct
|
||||
*/
|
||||
explicit PneumaticsControlModule(int module);
|
||||
PneumaticsControlModule(int busId, int module);
|
||||
|
||||
~PneumaticsControlModule() override = default;
|
||||
|
||||
@@ -196,17 +201,17 @@ class PneumaticsControlModule : public PneumaticsBase {
|
||||
class DataStore;
|
||||
friend class DataStore;
|
||||
friend class PneumaticsBase;
|
||||
PneumaticsControlModule(HAL_CTREPCMHandle handle, int module);
|
||||
PneumaticsControlModule(int busId, HAL_CTREPCMHandle handle, int module);
|
||||
|
||||
static std::shared_ptr<PneumaticsBase> GetForModule(int module);
|
||||
static std::shared_ptr<PneumaticsBase> GetForModule(int busId, int module);
|
||||
|
||||
std::shared_ptr<DataStore> m_dataStore;
|
||||
HAL_CTREPCMHandle m_handle;
|
||||
int m_module;
|
||||
|
||||
static wpi::mutex m_handleLock;
|
||||
static std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<DataStore>>>
|
||||
m_handleMap;
|
||||
static std::weak_ptr<DataStore>& GetDataStore(int module);
|
||||
static std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<DataStore>>[]>
|
||||
m_handleMaps;
|
||||
static std::weak_ptr<DataStore>& GetDataStore(int busId, int module);
|
||||
};
|
||||
} // namespace frc
|
||||
|
||||
@@ -38,16 +38,19 @@ class PowerDistribution : public wpi::Sendable,
|
||||
*
|
||||
* Detects the connected PDP/PDH using the default CAN ID (0 for CTRE and 1
|
||||
* for REV).
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
*/
|
||||
PowerDistribution();
|
||||
explicit PowerDistribution(int busId);
|
||||
|
||||
/**
|
||||
* Constructs a PowerDistribution object.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module The CAN ID of the PDP/PDH
|
||||
* @param moduleType The type of module
|
||||
*/
|
||||
PowerDistribution(int module, ModuleType moduleType);
|
||||
PowerDistribution(int busId, int module, ModuleType moduleType);
|
||||
|
||||
PowerDistribution(PowerDistribution&&) = default;
|
||||
PowerDistribution& operator=(PowerDistribution&&) = default;
|
||||
|
||||
@@ -336,9 +336,10 @@ class RobotController {
|
||||
/**
|
||||
* Get the current status of the CAN bus.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @return The status of the CAN bus
|
||||
*/
|
||||
static CANStatus GetCANStatus();
|
||||
static CANStatus GetCANStatus(int busId);
|
||||
|
||||
private:
|
||||
static std::function<uint64_t()> m_timeSource;
|
||||
|
||||
@@ -28,19 +28,21 @@ class Solenoid : public wpi::Sendable, public wpi::SendableHelper<Solenoid> {
|
||||
/**
|
||||
* Constructs a solenoid for a specified module and type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param module The module ID to use.
|
||||
* @param moduleType The module type to use.
|
||||
* @param channel The channel the solenoid is on.
|
||||
*/
|
||||
Solenoid(int module, PneumaticsModuleType moduleType, int channel);
|
||||
Solenoid(int busId, int module, PneumaticsModuleType moduleType, int channel);
|
||||
|
||||
/**
|
||||
* Constructs a solenoid for a default module and specified type.
|
||||
*
|
||||
* @param busId The bus ID.
|
||||
* @param moduleType The module type to use.
|
||||
* @param channel The channel the solenoid is on.
|
||||
*/
|
||||
Solenoid(PneumaticsModuleType moduleType, int channel);
|
||||
Solenoid(int busId, PneumaticsModuleType moduleType, int channel);
|
||||
|
||||
~Solenoid() override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user