[hal] Add frequency support to DutyCycle (#8076)

This commit is contained in:
Thad House
2025-07-14 23:46:17 -07:00
committed by GitHub
parent ef24c1df97
commit 3497a7d09f
31 changed files with 153 additions and 355 deletions

View File

@@ -46,9 +46,9 @@ Java_edu_wpi_first_hal_DutyCycleJNI_free
/*
* Class: edu_wpi_first_hal_DutyCycleJNI
* Method: getFrequency
* Signature: (I)I
* Signature: (I)D
*/
JNIEXPORT jint JNICALL
JNIEXPORT jdouble JNICALL
Java_edu_wpi_first_hal_DutyCycleJNI_getFrequency
(JNIEnv* env, jclass, jint handle)
{
@@ -91,36 +91,4 @@ Java_edu_wpi_first_hal_DutyCycleJNI_getHighTime
return retVal;
}
/*
* Class: edu_wpi_first_hal_DutyCycleJNI
* Method: getOutputScaleFactor
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_DutyCycleJNI_getOutputScaleFactor
(JNIEnv* env, jclass, jint handle)
{
int32_t status = 0;
auto retVal = HAL_GetDutyCycleOutputScaleFactor(
static_cast<HAL_DutyCycleHandle>(handle), &status);
CheckStatus(env, status);
return retVal;
}
/*
* Class: edu_wpi_first_hal_DutyCycleJNI
* Method: getFPGAIndex
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_DutyCycleJNI_getFPGAIndex
(JNIEnv* env, jclass, jint handle)
{
int32_t status = 0;
auto retVal = HAL_GetDutyCycleFPGAIndex(
static_cast<HAL_DutyCycleHandle>(handle), &status);
CheckStatus(env, status);
return retVal;
}
} // extern "C"

View File

@@ -91,9 +91,9 @@ Java_edu_wpi_first_hal_simulation_DutyCycleDataJNI_cancelFrequencyCallback
/*
* Class: edu_wpi_first_hal_simulation_DutyCycleDataJNI
* Method: getFrequency
* Signature: (I)I
* Signature: (I)D
*/
JNIEXPORT jint JNICALL
JNIEXPORT jdouble JNICALL
Java_edu_wpi_first_hal_simulation_DutyCycleDataJNI_getFrequency
(JNIEnv*, jclass, jint index)
{
@@ -103,11 +103,11 @@ Java_edu_wpi_first_hal_simulation_DutyCycleDataJNI_getFrequency
/*
* Class: edu_wpi_first_hal_simulation_DutyCycleDataJNI
* Method: setFrequency
* Signature: (II)V
* Signature: (ID)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DutyCycleDataJNI_setFrequency
(JNIEnv*, jclass, jint index, jint value)
(JNIEnv*, jclass, jint index, jdouble value)
{
HALSIM_SetDutyCycleFrequency(index, value);
}
@@ -174,16 +174,4 @@ Java_edu_wpi_first_hal_simulation_DutyCycleDataJNI_resetData
HALSIM_ResetDutyCycleData(index);
}
/*
* Class: edu_wpi_first_hal_simulation_DutyCycleDataJNI
* Method: findForChannel
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_DutyCycleDataJNI_findForChannel
(JNIEnv*, jclass, jint channel)
{
return HALSIM_FindDutyCycleForChannel(channel);
}
} // extern "C"

View File

@@ -52,8 +52,8 @@ void HAL_SetDutyCycleSimDevice(HAL_DutyCycleHandle handle,
* @param[out] status Error status variable. 0 on success.
* @return frequency in Hertz
*/
int32_t HAL_GetDutyCycleFrequency(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status);
double HAL_GetDutyCycleFrequency(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status);
/**
* Get the output ratio of the duty cycle signal.
@@ -77,30 +77,6 @@ double HAL_GetDutyCycleOutput(HAL_DutyCycleHandle dutyCycleHandle,
int32_t HAL_GetDutyCycleHighTime(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status);
/**
* Get the scale factor of the output.
*
* <p> An output equal to this value is always high, and then linearly scales
* down to 0. Divide a raw result by this in order to get the
* percentage between 0 and 1. Used by DMA.
*
* @param[in] dutyCycleHandle the duty cycle handle
* @param[out] status Error status variable. 0 on success.
* @return the output scale factor
*/
int32_t HAL_GetDutyCycleOutputScaleFactor(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status);
/**
* Get the FPGA index for the DutyCycle.
*
* @param[in] dutyCycleHandle the duty cycle handle
* @param[out] status Error status variable. 0 on success.
* @return the FPGA index
*/
int32_t HAL_GetDutyCycleFPGAIndex(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -11,10 +11,7 @@
extern "C" {
#endif
int32_t HALSIM_FindDutyCycleForChannel(int32_t channel);
void HALSIM_ResetDutyCycleData(int32_t index);
int32_t HALSIM_GetDutyCycleDigitalChannel(int32_t index);
int32_t HALSIM_RegisterDutyCycleInitializedCallback(int32_t index,
HAL_NotifyCallback callback,
@@ -39,8 +36,8 @@ int32_t HALSIM_RegisterDutyCycleFrequencyCallback(int32_t index,
void* param,
HAL_Bool initialNotify);
void HALSIM_CancelDutyCycleFrequencyCallback(int32_t index, int32_t uid);
int32_t HALSIM_GetDutyCycleFrequency(int32_t index);
void HALSIM_SetDutyCycleFrequency(int32_t index, int32_t frequency);
double HALSIM_GetDutyCycleFrequency(int32_t index);
void HALSIM_SetDutyCycleFrequency(int32_t index, double frequency);
void HALSIM_RegisterDutyCycleAllCallbacks(int32_t index,
HAL_NotifyCallback callback,

View File

@@ -4,11 +4,14 @@
#include "hal/DutyCycle.h"
#include <string>
#include "HALInitializer.h"
#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/Errors.h"
#include "hal/handles/HandlesInternal.h"
#include "hal/handles/LimitedHandleResource.h"
#include "hal/handles/IndexedHandleResource.h"
#include "mockdata/DutyCycleDataInternal.h"
using namespace hal;
@@ -16,16 +19,17 @@ using namespace hal;
namespace {
struct DutyCycle {
uint8_t index;
std::string previousAllocation;
};
struct Empty {};
} // namespace
static LimitedHandleResource<HAL_DutyCycleHandle, DutyCycle, kNumDutyCycles,
static IndexedHandleResource<HAL_DutyCycleHandle, DutyCycle, kNumDutyCycles,
HAL_HandleEnum::DutyCycle>* dutyCycleHandles;
namespace hal::init {
void InitializeDutyCycle() {
static LimitedHandleResource<HAL_DutyCycleHandle, DutyCycle, kNumDutyCycles,
static IndexedHandleResource<HAL_DutyCycleHandle, DutyCycle, kNumDutyCycles,
HAL_HandleEnum::DutyCycle>
dcH;
dutyCycleHandles = &dcH;
@@ -38,23 +42,25 @@ HAL_DutyCycleHandle HAL_InitializeDutyCycle(int32_t channel,
int32_t* status) {
hal::init::CheckInit();
HAL_DutyCycleHandle handle = dutyCycleHandles->Allocate();
if (handle == HAL_kInvalidHandle) {
*status = NO_AVAILABLE_RESOURCES;
return HAL_kInvalidHandle;
}
HAL_DutyCycleHandle handle = HAL_kInvalidHandle;
auto dutyCycle = dutyCycleHandles->Allocate(channel, &handle, status);
auto dutyCycle = dutyCycleHandles->Get(handle);
if (dutyCycle == nullptr) { // would only occur on thread issue
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
if (*status != 0) {
if (dutyCycle) {
hal::SetLastErrorPreviouslyAllocated(status, "SmartIo", channel,
dutyCycle->previousAllocation);
} else {
hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Duty Cycle",
0, kNumDutyCycles, channel);
}
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
}
int16_t index = getHandleIndex(handle);
SimDutyCycleData[index].digitalChannel = channel;
SimDutyCycleData[index].initialized = true;
SimDutyCycleData[index].simDevice = 0;
dutyCycle->index = index;
dutyCycle->previousAllocation = allocationLocation ? allocationLocation : "";
return handle;
}
void HAL_FreeDutyCycle(HAL_DutyCycleHandle dutyCycleHandle) {
@@ -75,8 +81,8 @@ void HAL_SetDutyCycleSimDevice(HAL_EncoderHandle handle,
SimDutyCycleData[dutyCycle->index].simDevice = device;
}
int32_t HAL_GetDutyCycleFrequency(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status) {
double HAL_GetDutyCycleFrequency(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status) {
auto dutyCycle = dutyCycleHandles->Get(dutyCycleHandle);
if (dutyCycle == nullptr) {
*status = HAL_HANDLE_ERROR;
@@ -110,19 +116,4 @@ int32_t HAL_GetDutyCycleHighTime(HAL_DutyCycleHandle dutyCycleHandle,
double period = 1e9 / SimDutyCycleData[dutyCycle->index].frequency; // ns
return period * SimDutyCycleData[dutyCycle->index].output;
}
int32_t HAL_GetDutyCycleOutputScaleFactor(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status) {
return 4e7 - 1;
}
int32_t HAL_GetDutyCycleFPGAIndex(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status) {
auto dutyCycle = dutyCycleHandles->Get(dutyCycleHandle);
if (dutyCycle == nullptr) {
*status = HAL_HANDLE_ERROR;
return -1;
}
return dutyCycle->index;
}
} // extern "C"

View File

@@ -31,7 +31,7 @@ constexpr int32_t kNumREVPDHModules = 63;
constexpr int32_t kNumREVPDHChannels = 24;
constexpr int32_t kNumPDSimModules = kNumREVPDHModules;
constexpr int32_t kNumPDSimChannels = kNumREVPDHChannels;
constexpr int32_t kNumDutyCycles = 8;
constexpr int32_t kNumDutyCycles = 6;
constexpr int32_t kNumAddressableLEDs = 1;
constexpr int32_t kNumREVPHModules = 63;
constexpr int32_t kNumREVPHChannels = 16;

View File

@@ -17,7 +17,6 @@ void InitializeDutyCycleData() {
DutyCycleData* hal::SimDutyCycleData;
void DutyCycleData::ResetData() {
digitalChannel = 0;
initialized.Reset(false);
simDevice = 0;
frequency.Reset(0);
@@ -25,22 +24,10 @@ void DutyCycleData::ResetData() {
}
extern "C" {
int32_t HALSIM_FindDutyCycleForChannel(int32_t channel) {
for (int i = 0; i < kNumDutyCycles; ++i) {
if (SimDutyCycleData[i].initialized &&
SimDutyCycleData[i].digitalChannel == channel) {
return i;
}
}
return -1;
}
void HALSIM_ResetDutyCycleData(int32_t index) {
SimDutyCycleData[index].ResetData();
}
int32_t HALSIM_GetDutyCycleDigitalChannel(int32_t index) {
return SimDutyCycleData[index].digitalChannel;
}
HAL_SimDeviceHandle HALSIM_GetDutyCycleSimDevice(int32_t index) {
return SimDutyCycleData[index].simDevice;
@@ -51,7 +38,7 @@ HAL_SimDeviceHandle HALSIM_GetDutyCycleSimDevice(int32_t index) {
SimDutyCycleData, LOWERNAME)
DEFINE_CAPI(HAL_Bool, Initialized, initialized)
DEFINE_CAPI(int32_t, Frequency, frequency)
DEFINE_CAPI(double, Frequency, frequency)
DEFINE_CAPI(double, Output, output)
#define REGISTER(NAME) \

View File

@@ -17,11 +17,10 @@ class DutyCycleData {
HAL_SIMDATAVALUE_DEFINE_NAME(Frequency)
public:
std::atomic<int32_t> digitalChannel{0};
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetInitializedName> initialized{
false};
std::atomic<HAL_SimDeviceHandle> simDevice;
SimDataValue<int32_t, HAL_MakeInt, GetFrequencyName> frequency{0};
SimDataValue<double, HAL_MakeDouble, GetFrequencyName> frequency{0};
SimDataValue<double, HAL_MakeDouble, GetOutputName> output{0};
virtual void ResetData();

View File

@@ -88,16 +88,47 @@ void HAL_FreeDutyCycle(HAL_DutyCycleHandle dutyCycleHandle) {
void HAL_SetDutyCycleSimDevice(HAL_EncoderHandle handle,
HAL_SimDeviceHandle device) {}
int32_t HAL_GetDutyCycleFrequency(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status) {
*status = HAL_HANDLE_ERROR;
return 0;
double HAL_GetDutyCycleFrequency(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status) {
auto port = smartIoHandles->Get(dutyCycleHandle, HAL_HandleEnum::DutyCycle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
}
uint16_t ret = 0;
*status = port->GetPwmInputPeriodMicroseconds(&ret);
if (ret == 0) {
return 0.0;
}
return 1000000.0 / ret;
}
double HAL_GetDutyCycleOutput(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status) {
*status = HAL_HANDLE_ERROR;
return 0;
auto port = smartIoHandles->Get(dutyCycleHandle, HAL_HandleEnum::DutyCycle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0.0;
}
uint16_t highTime = 0;
*status = port->GetPwmInputMicroseconds(&highTime);
uint16_t period = 0;
*status = port->GetPwmInputPeriodMicroseconds(&period);
if (period == 0) {
return 0.0;
}
if (highTime >= period) {
return 1.0;
}
return static_cast<double>(highTime) / static_cast<double>(period);
}
int32_t HAL_GetDutyCycleHighTime(HAL_DutyCycleHandle dutyCycleHandle,
@@ -105,23 +136,11 @@ int32_t HAL_GetDutyCycleHighTime(HAL_DutyCycleHandle dutyCycleHandle,
auto port = smartIoHandles->Get(dutyCycleHandle, HAL_HandleEnum::DutyCycle);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
return 0;
}
uint16_t ret = 0;
*status = port->GetPwmInputMicroseconds(&ret);
return static_cast<int32_t>(ret) * 1000;
}
int32_t HAL_GetDutyCycleOutputScaleFactor(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status) {
*status = HAL_HANDLE_ERROR;
return 0;
}
int32_t HAL_GetDutyCycleFPGAIndex(HAL_DutyCycleHandle dutyCycleHandle,
int32_t* status) {
*status = HAL_HANDLE_ERROR;
return 0;
}
} // extern "C"

View File

@@ -35,11 +35,11 @@ int32_t SmartIo::InitializeMode(SmartIoMode mode) {
modePublisher = inst.GetIntegerTopic(subTableString + "type").Publish();
getSubscriber =
inst.GetIntegerTopic(subTableString + "valget").Subscribe(0, options);
frequencySubscriber =
inst.GetIntegerTopic(subTableString + "freqget").Subscribe(0, options);
periodGetSubscriber =
inst.GetIntegerTopic(subTableString + "periodget").Subscribe(0, options);
setPublisher =
inst.GetIntegerTopic(subTableString + "valset").Publish(options);
periodPublisher =
periodSetPublisher =
inst.GetIntegerTopic(subTableString + "periodset").Publish(options);
currentMode = mode;
@@ -107,6 +107,17 @@ int32_t SmartIo::GetPwmInputMicroseconds(uint16_t* microseconds) {
return 0;
}
int32_t SmartIo::GetPwmInputPeriodMicroseconds(uint16_t* microseconds) {
if (currentMode != SmartIoMode::PwmInput) {
return INCOMPATIBLE_STATE;
}
int val = periodGetSubscriber.Get();
*microseconds = val;
return 0;
}
int32_t SmartIo::SetPwmOutputPeriod(PwmOutputPeriod period) {
if (currentMode != SmartIoMode::PwmOutput) {
return INCOMPATIBLE_STATE;
@@ -117,7 +128,7 @@ int32_t SmartIo::SetPwmOutputPeriod(PwmOutputPeriod period) {
case PwmOutputPeriod::k10ms:
case PwmOutputPeriod::k5ms:
case PwmOutputPeriod::k2ms:
periodPublisher.Set(static_cast<int>(period));
periodSetPublisher.Set(static_cast<int>(period));
return 0;
default:

View File

@@ -19,12 +19,12 @@ constexpr int32_t kPwmAlwaysHigh = 0xFFFF;
enum class SmartIoMode {
DigitalInput = 0,
DigitalOutput,
AnalogInput,
PwmInput,
PwmOutput,
SingleCounterRising,
SingleCounterFalling,
DigitalOutput = 1,
AnalogInput = 2,
PwmInput = 3,
PwmOutput = 4,
SingleCounterRising = 5,
SingleCounterFalling = 6,
};
enum class PwmOutputPeriod {
@@ -43,8 +43,8 @@ struct SmartIo {
nt::IntegerPublisher setPublisher;
nt::IntegerSubscriber getSubscriber;
nt::IntegerPublisher periodPublisher;
nt::IntegerSubscriber frequencySubscriber;
nt::IntegerPublisher periodSetPublisher;
nt::IntegerSubscriber periodGetSubscriber;
int32_t InitializeMode(SmartIoMode mode);
int32_t SwitchDioDirection(bool input);
@@ -53,6 +53,7 @@ struct SmartIo {
int32_t GetDigitalInput(bool* value);
int32_t GetPwmInputMicroseconds(uint16_t* microseconds);
int32_t GetPwmInputPeriodMicroseconds(uint16_t* microseconds);
int32_t SetPwmOutputPeriod(PwmOutputPeriod period);

View File

@@ -7,16 +7,9 @@
#include "hal/simulation/SimDataValue.h"
extern "C" {
int32_t HALSIM_FindDutyCycleForChannel(int32_t channel) {
return 0;
}
void HALSIM_ResetDutyCycleData(int32_t index) {}
int32_t HALSIM_GetDutyCycleDigitalChannel(int32_t index) {
return 0;
}
HAL_SimDeviceHandle HALSIM_GetDutyCycleSimDevice(int32_t index) {
return 0;
}
@@ -25,7 +18,7 @@ HAL_SimDeviceHandle HALSIM_GetDutyCycleSimDevice(int32_t index) {
HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, DutyCycle##CAPINAME, RETURN)
DEFINE_CAPI(HAL_Bool, Initialized, false)
DEFINE_CAPI(int32_t, Frequency, 0)
DEFINE_CAPI(double, Frequency, 0)
DEFINE_CAPI(double, Output, 0)
void HALSIM_RegisterDutyCycleAllCallbacks(int32_t index,