2024-12-08 12:02:22 -08:00
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
|
|
|
|
|
|
|
|
|
#include "SmartIo.h"
|
|
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
|
|
|
|
|
|
#include "HALInitializer.h"
|
2025-01-16 09:49:40 -08:00
|
|
|
#include "SystemServerInternal.h"
|
2024-12-08 12:02:22 -08:00
|
|
|
|
|
|
|
|
namespace hal {
|
|
|
|
|
|
|
|
|
|
wpi::mutex smartIoMutex;
|
|
|
|
|
DigitalHandleResource<HAL_DigitalHandle, SmartIo, kNumSmartIo>* smartIoHandles;
|
|
|
|
|
|
|
|
|
|
namespace init {
|
|
|
|
|
void InitializeSmartIo() {
|
|
|
|
|
static DigitalHandleResource<HAL_DigitalHandle, SmartIo, kNumSmartIo> dcH;
|
|
|
|
|
smartIoHandles = &dcH;
|
|
|
|
|
}
|
|
|
|
|
} // namespace init
|
|
|
|
|
|
|
|
|
|
int32_t SmartIo::InitializeMode(SmartIoMode mode) {
|
|
|
|
|
auto inst = hal::GetSystemServer();
|
|
|
|
|
|
|
|
|
|
nt::PubSubOptions options;
|
|
|
|
|
options.sendAll = true;
|
|
|
|
|
options.keepDuplicates = true;
|
|
|
|
|
options.periodic = 0.005;
|
|
|
|
|
|
|
|
|
|
auto channelString = std::to_string(channel);
|
2024-12-22 11:45:44 -08:00
|
|
|
auto subTableString = "/io/" + channelString + "/";
|
2024-12-08 12:02:22 -08:00
|
|
|
|
2025-07-18 00:17:18 -04:00
|
|
|
modePublisher =
|
|
|
|
|
inst.GetIntegerTopic(subTableString + "type").Publish(options);
|
2024-12-22 11:45:44 -08:00
|
|
|
getSubscriber =
|
2025-01-12 16:58:46 -08:00
|
|
|
inst.GetIntegerTopic(subTableString + "valget").Subscribe(0, options);
|
2025-07-14 23:46:17 -07:00
|
|
|
periodGetSubscriber =
|
|
|
|
|
inst.GetIntegerTopic(subTableString + "periodget").Subscribe(0, options);
|
2025-01-12 16:58:46 -08:00
|
|
|
setPublisher =
|
|
|
|
|
inst.GetIntegerTopic(subTableString + "valset").Publish(options);
|
2025-07-14 23:46:17 -07:00
|
|
|
periodSetPublisher =
|
2025-01-12 16:58:46 -08:00
|
|
|
inst.GetIntegerTopic(subTableString + "periodset").Publish(options);
|
2024-12-08 12:02:22 -08:00
|
|
|
|
|
|
|
|
currentMode = mode;
|
|
|
|
|
switch (mode) {
|
2025-01-12 16:58:46 -08:00
|
|
|
// These need to set a 0 output
|
|
|
|
|
case SmartIoMode::DigitalOutput:
|
|
|
|
|
case SmartIoMode::PwmOutput:
|
2024-12-08 12:02:22 -08:00
|
|
|
setPublisher.Set(0);
|
2025-01-12 16:58:46 -08:00
|
|
|
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;
|
2024-12-08 12:02:22 -08:00
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
|
|
return INCOMPATIBLE_STATE;
|
|
|
|
|
}
|
2025-01-12 16:58:46 -08:00
|
|
|
|
|
|
|
|
modePublisher.Set(static_cast<int>(mode));
|
|
|
|
|
return 0;
|
2024-12-08 12:02:22 -08:00
|
|
|
}
|
|
|
|
|
|
2025-01-12 16:58:46 -08:00
|
|
|
int32_t SmartIo::SwitchDioDirection(bool input) {
|
|
|
|
|
if (currentMode != SmartIoMode::DigitalInput &&
|
|
|
|
|
currentMode != SmartIoMode::DigitalOutput) {
|
|
|
|
|
return INCOMPATIBLE_STATE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
modePublisher.Set(input ? 0 : 1);
|
|
|
|
|
currentMode = input ? SmartIoMode::DigitalInput : SmartIoMode::DigitalOutput;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t SmartIo::SetDigitalOutput(bool value) {
|
|
|
|
|
if (currentMode != SmartIoMode::DigitalInput &&
|
|
|
|
|
currentMode != SmartIoMode::DigitalOutput) {
|
|
|
|
|
return INCOMPATIBLE_STATE;
|
|
|
|
|
}
|
|
|
|
|
setPublisher.Set(value ? 255.0 : 0.0);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t SmartIo::GetDigitalInput(bool* value) {
|
|
|
|
|
if (currentMode != SmartIoMode::DigitalInput &&
|
|
|
|
|
currentMode != SmartIoMode::DigitalOutput) {
|
|
|
|
|
return INCOMPATIBLE_STATE;
|
|
|
|
|
}
|
|
|
|
|
*value = getSubscriber.Get() != 0;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-15 11:57:31 -08:00
|
|
|
int32_t SmartIo::GetPwmInputMicroseconds(uint16_t* microseconds) {
|
|
|
|
|
if (currentMode != SmartIoMode::PwmInput) {
|
|
|
|
|
return INCOMPATIBLE_STATE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int val = getSubscriber.Get();
|
|
|
|
|
*microseconds = val;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-14 23:46:17 -07:00
|
|
|
int32_t SmartIo::GetPwmInputPeriodMicroseconds(uint16_t* microseconds) {
|
|
|
|
|
if (currentMode != SmartIoMode::PwmInput) {
|
|
|
|
|
return INCOMPATIBLE_STATE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int val = periodGetSubscriber.Get();
|
|
|
|
|
*microseconds = val;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-12 16:58:46 -08:00
|
|
|
int32_t SmartIo::SetPwmOutputPeriod(PwmOutputPeriod period) {
|
|
|
|
|
if (currentMode != SmartIoMode::PwmOutput) {
|
2024-12-08 12:02:22 -08:00
|
|
|
return INCOMPATIBLE_STATE;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-12 16:58:46 -08:00
|
|
|
switch (period) {
|
|
|
|
|
case PwmOutputPeriod::k20ms:
|
|
|
|
|
case PwmOutputPeriod::k10ms:
|
|
|
|
|
case PwmOutputPeriod::k5ms:
|
|
|
|
|
case PwmOutputPeriod::k2ms:
|
2025-07-14 23:46:17 -07:00
|
|
|
periodSetPublisher.Set(static_cast<int>(period));
|
2025-01-12 16:58:46 -08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return PARAMETER_OUT_OF_RANGE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t SmartIo::SetPwmMicroseconds(uint16_t microseconds) {
|
|
|
|
|
if (currentMode != SmartIoMode::PwmOutput) {
|
|
|
|
|
return INCOMPATIBLE_STATE;
|
|
|
|
|
}
|
2024-12-08 12:02:22 -08:00
|
|
|
|
2024-12-08 22:08:05 -08:00
|
|
|
if (microseconds > 4095) {
|
|
|
|
|
microseconds = 4095;
|
2024-12-08 12:02:22 -08:00
|
|
|
}
|
|
|
|
|
|
2024-12-22 11:45:44 -08:00
|
|
|
setPublisher.Set(microseconds);
|
2024-12-08 12:02:22 -08:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t SmartIo::GetPwmMicroseconds(uint16_t* microseconds) {
|
2025-01-12 16:58:46 -08:00
|
|
|
if (currentMode != SmartIoMode::PwmOutput) {
|
2024-12-08 12:02:22 -08:00
|
|
|
return INCOMPATIBLE_STATE;
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-22 11:45:44 -08:00
|
|
|
int val = getSubscriber.Get();
|
2024-12-08 12:02:22 -08:00
|
|
|
|
|
|
|
|
// Get to 0-2, then scale to 0-4096;
|
2024-12-22 11:45:44 -08:00
|
|
|
*microseconds = val;
|
2024-12-08 12:02:22 -08:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-14 11:30:44 -08:00
|
|
|
int32_t SmartIo::GetAnalogInput(uint16_t* value) {
|
|
|
|
|
if (currentMode != SmartIoMode::AnalogInput) {
|
|
|
|
|
return INCOMPATIBLE_STATE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int val = getSubscriber.Get();
|
|
|
|
|
|
|
|
|
|
*value = val;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-28 08:58:34 -08:00
|
|
|
int32_t SmartIo::GetCounter(int32_t* value) {
|
|
|
|
|
if (currentMode != SmartIoMode::SingleCounterFalling &&
|
|
|
|
|
currentMode != SmartIoMode::SingleCounterRising) {
|
|
|
|
|
return INCOMPATIBLE_STATE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t val = getSubscriber.Get();
|
|
|
|
|
|
|
|
|
|
*value = val;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-08 12:02:22 -08:00
|
|
|
} // namespace hal
|