[hal] Switch SmartIO to mrclib (#8960)

This commit is contained in:
Thad House
2026-06-06 14:54:49 -07:00
committed by GitHub
parent edf77fa007
commit 71ed28f768
9 changed files with 100 additions and 217 deletions

View File

@@ -66,7 +66,7 @@ void HAL_FreeDutyCycle(HAL_DutyCycleHandle dutyCycleHandle) {
SimDutyCycleData[dutyCycle->index].initialized = false;
}
void HAL_SetDutyCycleSimDevice(HAL_EncoderHandle handle,
void HAL_SetDutyCycleSimDevice(HAL_DutyCycleHandle handle,
HAL_SimDeviceHandle device) {
auto dutyCycle = dutyCycleHandles->Get(handle);
if (dutyCycle == nullptr) {

View File

@@ -27,18 +27,9 @@
using namespace wpi::hal;
#define IO_PREFIX "/io/"
namespace {
constexpr const char* kLedsKey = IO_PREFIX "leds";
struct AddressableLEDs {
explicit AddressableLEDs(wpi::nt::NetworkTableInstance inst)
: rawPub{inst.GetRawTopic(kLedsKey).Publish(
"raw", {.periodic = 0.005, .sendAll = true})} {}
wpi::nt::RawPublisher rawPub;
uint8_t s_buffer[HAL_ADDRESSABLE_LED_MAX_LEN * 3];
};
@@ -77,7 +68,7 @@ void ConvertAndCopyLEDData(void* dst, const struct HAL_AddressableLEDData* src,
namespace wpi::hal::init {
void InitializeAddressableLED() {
static AddressableLEDs leds_static{wpi::hal::GetSystemServer()};
static AddressableLEDs leds_static;
leds = &leds_static;
}
} // namespace wpi::hal::init
@@ -106,7 +97,8 @@ HAL_AddressableLEDHandle HAL_InitializeAddressableLED(
auto [handle, port] = *resource;
port->channel = channel;
*status = port->InitializeMode(SmartIoMode::AddressableLED);
*status =
port->InitializeMode(MRC_SmartIOMode::MRC_SmartIOMode_AddressableLED);
if (*status != 0) {
smartIoHandles->Free(handle, HAL_HandleEnum::ADDRESSABLE_LED);
return HAL_INVALID_HANDLE;
@@ -172,6 +164,6 @@ void HAL_SetAddressableLEDData(int32_t start, int32_t length,
return;
}
ConvertAndCopyLEDData(&leds->s_buffer[start * 3], data, length, colorOrder);
leds->rawPub.Set(leds->s_buffer);
MRC_SmartIO_SetLedBuffer(leds->s_buffer, sizeof(leds->s_buffer));
}
} // extern "C"

View File

@@ -45,7 +45,7 @@ HAL_AnalogInputHandle HAL_InitializeAnalogInputPort(
auto [handle, port] = *resource;
port->channel = channel;
*status = port->InitializeMode(SmartIoMode::AnalogInput);
*status = port->InitializeMode(MRC_SmartIOMode::MRC_SmartIOMode_AnalogInput);
if (*status != 0) {
smartIoHandles->Free(handle, HAL_HandleEnum::ANALOG_INPUT);
return HAL_INVALID_HANDLE;

View File

@@ -45,9 +45,9 @@ HAL_CounterHandle HAL_InitializeCounter(int channel, HAL_Bool risingEdge,
auto [handle, port] = *resource;
port->channel = channel;
*status =
port->InitializeMode(risingEdge ? SmartIoMode::SingleCounterRising
: SmartIoMode::SingleCounterFalling);
*status = port->InitializeMode(
risingEdge ? MRC_SmartIOMode::MRC_SmartIOMode_SingleCounterRising
: MRC_SmartIOMode::MRC_SmartIOMode_SingleCounterFalling);
if (*status != 0) {
smartIoHandles->Free(handle, HAL_HandleEnum::COUNTER);
return HAL_INVALID_HANDLE;

View File

@@ -46,8 +46,9 @@ HAL_DigitalHandle HAL_InitializeDIOPort(int32_t channel, HAL_Bool input,
auto [handle, port] = *resource;
port->channel = channel;
*status = port->InitializeMode(input ? SmartIoMode::DigitalInput
: SmartIoMode::DigitalOutput);
*status = port->InitializeMode(
input ? MRC_SmartIOMode::MRC_SmartIOMode_DigitalInput
: MRC_SmartIOMode::MRC_SmartIOMode_DigitalOutput);
if (*status != 0) {
smartIoHandles->Free(handle, HAL_HandleEnum::DIO);
return HAL_INVALID_HANDLE;
@@ -158,9 +159,9 @@ HAL_Bool HAL_GetDIODirection(HAL_DigitalHandle dioPortHandle, int32_t* status) {
}
switch (port->currentMode) {
case SmartIoMode::DigitalInput:
case MRC_SmartIOMode::MRC_SmartIOMode_DigitalInput:
return true;
case SmartIoMode::DigitalOutput:
case MRC_SmartIOMode::MRC_SmartIOMode_DigitalOutput:
return false;
default:
*status = HAL_INCOMPATIBLE_STATE;

View File

@@ -45,7 +45,7 @@ HAL_DutyCycleHandle HAL_InitializeDutyCycle(int32_t channel,
auto [handle, port] = *resource;
port->channel = channel;
*status = port->InitializeMode(SmartIoMode::PwmInput);
*status = port->InitializeMode(MRC_SmartIOMode::MRC_SmartIOMode_PwmInput);
if (*status != 0) {
smartIoHandles->Free(handle, HAL_HandleEnum::DUTY_CYCLE);
return HAL_INVALID_HANDLE;
@@ -68,7 +68,7 @@ void HAL_FreeDutyCycle(HAL_DutyCycleHandle dutyCycleHandle) {
while (port.use_count() != 1) {
auto current = wpi::hal::monotonic_clock::now();
if (start + std::chrono::seconds(1) < current) {
std::puts("DIO handle free timeout");
std::puts("DutyCycle handle free timeout");
std::fflush(stdout);
break;
}
@@ -76,7 +76,7 @@ void HAL_FreeDutyCycle(HAL_DutyCycleHandle dutyCycleHandle) {
}
}
void HAL_SetDutyCycleSimDevice(HAL_EncoderHandle handle,
void HAL_SetDutyCycleSimDevice(HAL_DutyCycleHandle handle,
HAL_SimDeviceHandle device) {}
double HAL_GetDutyCycleFrequency(HAL_DutyCycleHandle dutyCycleHandle,

View File

@@ -48,7 +48,7 @@ HAL_DigitalHandle HAL_InitializePWMPort(int32_t channel,
auto [handle, port] = *resource;
port->channel = channel;
*status = port->InitializeMode(SmartIoMode::PwmOutput);
*status = port->InitializeMode(MRC_SmartIOMode::MRC_SmartIOMode_PwmOutput);
if (*status != 0) {
smartIoHandles->Free(handle, HAL_HandleEnum::PWM);
return HAL_INVALID_HANDLE;
@@ -112,7 +112,7 @@ void HAL_SetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
return;
}
*status = port->SetPwmMicroseconds(microsecondPulseTime);
*status = port->SetPwmOutputMicroseconds(microsecondPulseTime);
}
int32_t HAL_GetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
@@ -124,7 +124,7 @@ int32_t HAL_GetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
}
uint16_t microseconds = 0;
*status = port->GetPwmMicroseconds(&microseconds);
*status = port->GetPwmOutputMicroseconds(&microseconds);
return microseconds;
}
@@ -138,14 +138,17 @@ void HAL_SetPWMOutputPeriod(HAL_DigitalHandle pwmPortHandle, int32_t period,
switch (period) {
case 0:
*status = port->SetPwmOutputPeriod(wpi::hal::PwmOutputPeriod::k5ms);
*status = port->SetPwmOutputPeriod(
MRC_PwmOutputPeriod::MRC_PwmOutputPeriod_5ms);
break;
case 1:
case 2:
*status = port->SetPwmOutputPeriod(wpi::hal::PwmOutputPeriod::k10ms);
*status = port->SetPwmOutputPeriod(
MRC_PwmOutputPeriod::MRC_PwmOutputPeriod_10ms);
break;
case 3:
*status = port->SetPwmOutputPeriod(wpi::hal::PwmOutputPeriod::k20ms);
*status = port->SetPwmOutputPeriod(
MRC_PwmOutputPeriod::MRC_PwmOutputPeriod_20ms);
break;
default:
*status = HAL_PARAMETER_OUT_OF_RANGE;

View File

@@ -5,7 +5,7 @@
#include "SmartIo.hpp"
#include "HALInitializer.hpp"
#include "SystemServerInternal.hpp"
#include "mrclib/SmartIO.h"
#include "wpi/hal/AddressableLEDTypes.h"
#include "wpi/hal/Errors.h"
@@ -19,204 +19,118 @@ void InitializeSmartIo() {
static DigitalHandleResource<HAL_DigitalHandle, SmartIo, kNumSmartIo> dcH;
smartIoHandles = &dcH;
}
} // namespace init
int32_t SmartIo::InitializeMode(SmartIoMode mode) {
auto inst = wpi::hal::GetSystemServer();
namespace {
struct SmartIoInitializer {
MRC_Status status = MRC_SmartIO_Initialize();
};
} // namespace
wpi::nt::PubSubOptions options;
options.sendAll = true;
options.keepDuplicates = true;
options.periodic = 0.005;
SmartIo::~SmartIo() noexcept {
MRC_SmartIO_Close(channel);
}
auto channelString = std::to_string(channel);
auto subTableString = "/io/" + channelString + "/";
int32_t SmartIo::InitializeMode(MRC_SmartIOMode mode) {
static SmartIoInitializer mrcSmartIo;
modePublisher =
inst.GetIntegerTopic(subTableString + "type").Publish(options);
getSubscriber =
inst.GetIntegerTopic(subTableString + "valget").Subscribe(0, options);
periodGetSubscriber =
inst.GetIntegerTopic(subTableString + "periodget").Subscribe(0, options);
setPublisher =
inst.GetIntegerTopic(subTableString + "valset").Publish(options);
periodSetPublisher =
inst.GetIntegerTopic(subTableString + "periodset").Publish(options);
ledcountPublisher =
inst.GetIntegerTopic(subTableString + "ledcount").Publish(options);
ledoffsetPublisher =
inst.GetIntegerTopic(subTableString + "ledoffset").Publish(options);
currentMode = mode;
switch (mode) {
// These need to set a 0 output
case SmartIoMode::DigitalOutput:
case SmartIoMode::PwmOutput:
setPublisher.Set(0);
break;
case SmartIoMode::AddressableLED:
ledcountPublisher.Set(0);
ledoffsetPublisher.Set(0);
break;
// These don't need to set any value
case SmartIoMode::DigitalInput:
case SmartIoMode::AnalogInput:
case SmartIoMode::PwmInput:
case SmartIoMode::SingleCounterRising:
case SmartIoMode::SingleCounterFalling:
break;
default:
return HAL_INCOMPATIBLE_STATE;
if (mrcSmartIo.status != 0) {
return mrcSmartIo.status;
}
modePublisher.Set(static_cast<int>(mode));
return 0;
MRC_Status ret = MRC_SmartIO_InitializeMode(channel, mode);
if (ret == 0) {
currentMode = mode;
}
return ret;
}
int32_t SmartIo::SwitchDioDirection(bool input) {
if (currentMode != SmartIoMode::DigitalInput &&
currentMode != SmartIoMode::DigitalOutput) {
return HAL_INCOMPATIBLE_STATE;
MRC_Status ret = MRC_SmartIO_SwitchDirection(channel, input);
if (ret == 0) {
currentMode = input ? MRC_SmartIOMode::MRC_SmartIOMode_DigitalInput
: MRC_SmartIOMode::MRC_SmartIOMode_DigitalOutput;
}
modePublisher.Set(input ? 0 : 1);
currentMode = input ? SmartIoMode::DigitalInput : SmartIoMode::DigitalOutput;
return 0;
return ret;
}
int32_t SmartIo::SetDigitalOutput(bool value) {
if (currentMode != SmartIoMode::DigitalInput &&
currentMode != SmartIoMode::DigitalOutput) {
return HAL_INCOMPATIBLE_STATE;
}
setPublisher.Set(value ? 255.0 : 0.0);
return 0;
return MRC_SmartIO_SetDigitalOutput(channel, value);
}
int32_t SmartIo::GetDigitalInput(bool* value) {
if (currentMode != SmartIoMode::DigitalInput &&
currentMode != SmartIoMode::DigitalOutput) {
return HAL_INCOMPATIBLE_STATE;
MRC_Bool val;
int32_t status = MRC_SmartIO_GetDigitalInput(channel, &val);
if (status == 0) {
*value = val ? true : false;
}
*value = getSubscriber.Get() != 0;
return 0;
return status;
}
int32_t SmartIo::GetPwmInputMicroseconds(uint16_t* microseconds) {
if (currentMode != SmartIoMode::PwmInput) {
return HAL_INCOMPATIBLE_STATE;
int32_t microsecondsInt;
int32_t status =
MRC_SmartIO_GetPwmInputMicroseconds(channel, &microsecondsInt);
if (status == 0) {
*microseconds = microsecondsInt;
}
int val = getSubscriber.Get();
*microseconds = val;
return 0;
return status;
}
int32_t SmartIo::GetPwmInputPeriodMicroseconds(uint16_t* microseconds) {
if (currentMode != SmartIoMode::PwmInput) {
return HAL_INCOMPATIBLE_STATE;
int32_t microsecondsInt;
int32_t status =
MRC_SmartIO_GetPwmInputPeriodMicroseconds(channel, &microsecondsInt);
if (status == 0) {
*microseconds = microsecondsInt;
}
int val = periodGetSubscriber.Get();
*microseconds = val;
return 0;
return status;
}
int32_t SmartIo::SetPwmOutputPeriod(PwmOutputPeriod period) {
if (currentMode != SmartIoMode::PwmOutput) {
return HAL_INCOMPATIBLE_STATE;
}
switch (period) {
case PwmOutputPeriod::k20ms:
case PwmOutputPeriod::k10ms:
case PwmOutputPeriod::k5ms:
case PwmOutputPeriod::k2ms:
periodSetPublisher.Set(static_cast<int>(period));
return 0;
default:
return HAL_PARAMETER_OUT_OF_RANGE;
}
int32_t SmartIo::SetPwmOutputPeriod(MRC_PwmOutputPeriod period) {
return MRC_SmartIO_SetPwmOutputPeriod(channel, period);
}
int32_t SmartIo::SetPwmMicroseconds(uint16_t microseconds) {
if (currentMode != SmartIoMode::PwmOutput) {
return HAL_INCOMPATIBLE_STATE;
int32_t SmartIo::SetPwmOutputMicroseconds(uint16_t microseconds) {
MRC_Status ret = MRC_SmartIO_SetPwmOutputMicroseconds(channel, microseconds);
if (ret != 0) {
setPwmOutputMicrosecondsValue = 0;
} else {
setPwmOutputMicrosecondsValue = microseconds;
}
if (microseconds > 4095) {
microseconds = 4095;
}
setPublisher.Set(microseconds);
return 0;
return ret;
}
int32_t SmartIo::GetPwmMicroseconds(uint16_t* microseconds) {
if (currentMode != SmartIoMode::PwmOutput) {
return HAL_INCOMPATIBLE_STATE;
}
int val = getSubscriber.Get();
// Get to 0-2, then scale to 0-4096;
*microseconds = val;
return 0;
int32_t SmartIo::GetPwmOutputMicroseconds(uint16_t* microseconds) {
*microseconds = setPwmOutputMicrosecondsValue;
return MRC_STATUS_SUCCESS;
}
int32_t SmartIo::GetAnalogInput(uint16_t* value) {
if (currentMode != SmartIoMode::AnalogInput) {
return HAL_INCOMPATIBLE_STATE;
int32_t valueInt;
int32_t status = MRC_SmartIO_GetAnalogInput(channel, &valueInt);
if (status == 0) {
*value = valueInt;
}
int val = getSubscriber.Get();
*value = val;
return 0;
return status;
}
int32_t SmartIo::GetCounter(int32_t* value) {
if (currentMode != SmartIoMode::SingleCounterFalling &&
currentMode != SmartIoMode::SingleCounterRising) {
return HAL_INCOMPATIBLE_STATE;
int32_t valueInt;
int32_t status = MRC_SmartIO_GetCounter(channel, &valueInt);
if (status == 0) {
*value = valueInt;
}
int32_t val = getSubscriber.Get();
*value = val;
return 0;
return status;
}
int32_t SmartIo::SetLedStart(int32_t start) {
if (currentMode != SmartIoMode::AddressableLED) {
return HAL_INCOMPATIBLE_STATE;
}
if (start < 0 || start >= HAL_ADDRESSABLE_LED_MAX_LEN) {
return HAL_PARAMETER_OUT_OF_RANGE;
}
ledoffsetPublisher.Set(start);
return 0;
return MRC_SmartIO_SetLedStartIndex(channel, start);
}
int32_t SmartIo::SetLedLength(int32_t length) {
if (currentMode != SmartIoMode::AddressableLED) {
return HAL_INCOMPATIBLE_STATE;
}
if (length < 0 || length >= HAL_ADDRESSABLE_LED_MAX_LEN) {
return HAL_PARAMETER_OUT_OF_RANGE;
}
ledcountPublisher.Set(length);
return 0;
return MRC_SmartIO_SetLedLength(channel, length);
}
} // namespace wpi::hal

View File

@@ -7,48 +7,22 @@
#include <string>
#include "PortsInternal.hpp"
#include "mrclib/SmartIO.h"
#include "wpi/hal/handles/DigitalHandleResource.hpp"
#include "wpi/nt/IntegerTopic.hpp"
namespace wpi::hal {
constexpr int32_t kPwmDisabled = 0;
constexpr int32_t kPwmAlwaysHigh = 0xFFFF;
enum class SmartIoMode {
DigitalInput = 0,
DigitalOutput = 1,
AnalogInput = 2,
PwmInput = 3,
PwmOutput = 4,
SingleCounterRising = 5,
SingleCounterFalling = 6,
AddressableLED = 13,
};
enum class PwmOutputPeriod {
k20ms = 0,
k10ms,
k5ms,
k2ms,
};
struct SmartIo {
~SmartIo() noexcept;
uint8_t channel;
std::string previousAllocation;
SmartIoMode currentMode{SmartIoMode::DigitalInput};
wpi::nt::IntegerPublisher modePublisher;
MRC_SmartIOMode currentMode{MRC_SmartIOMode::MRC_SmartIOMode_DigitalInput};
uint16_t setPwmOutputMicrosecondsValue{0};
wpi::nt::IntegerPublisher setPublisher;
wpi::nt::IntegerSubscriber getSubscriber;
wpi::nt::IntegerPublisher periodSetPublisher;
wpi::nt::IntegerSubscriber periodGetSubscriber;
wpi::nt::IntegerPublisher ledcountPublisher;
wpi::nt::IntegerPublisher ledoffsetPublisher;
int32_t InitializeMode(SmartIoMode mode);
int32_t InitializeMode(MRC_SmartIOMode mode);
int32_t SwitchDioDirection(bool input);
int32_t SetDigitalOutput(bool value);
@@ -57,10 +31,9 @@ struct SmartIo {
int32_t GetPwmInputMicroseconds(uint16_t* microseconds);
int32_t GetPwmInputPeriodMicroseconds(uint16_t* microseconds);
int32_t SetPwmOutputPeriod(PwmOutputPeriod period);
int32_t SetPwmMicroseconds(uint16_t microseconds);
int32_t GetPwmMicroseconds(uint16_t* microseconds);
int32_t SetPwmOutputPeriod(MRC_PwmOutputPeriod period);
int32_t SetPwmOutputMicroseconds(uint16_t microseconds);
int32_t GetPwmOutputMicroseconds(uint16_t* microseconds);
int32_t GetAnalogInput(uint16_t* value);