diff --git a/hal/src/main/java/edu/wpi/first/hal/DutyCycleJNI.java b/hal/src/main/java/edu/wpi/first/hal/DutyCycleJNI.java index 2dcf0f2113..f2737d8c7c 100644 --- a/hal/src/main/java/edu/wpi/first/hal/DutyCycleJNI.java +++ b/hal/src/main/java/edu/wpi/first/hal/DutyCycleJNI.java @@ -13,7 +13,7 @@ public class DutyCycleJNI extends JNIWrapper { public static native double getOutput(int handle); - public static native int getOutputRaw(int handle); + public static native int getHighTime(int handle); public static native int getOutputScaleFactor(int handle); diff --git a/hal/src/main/native/athena/AnalogTrigger.cpp b/hal/src/main/native/athena/AnalogTrigger.cpp index d9e2b9251c..47ef4f2fc2 100644 --- a/hal/src/main/native/athena/AnalogTrigger.cpp +++ b/hal/src/main/native/athena/AnalogTrigger.cpp @@ -5,6 +5,7 @@ #include "hal/AnalogTrigger.h" #include "AnalogInternal.h" +#include "ConstantsInternal.h" #include "DutyCycleInternal.h" #include "HALInitializer.h" #include "HALInternal.h" @@ -147,16 +148,10 @@ void HAL_SetAnalogTriggerLimitsDutyCycle( return; } - int32_t scaleFactor = - HAL_GetDutyCycleOutputScaleFactor(trigger->handle, status); - if (*status != 0) { - return; - } - - trigger->trigger->writeLowerLimit(static_cast(scaleFactor * lower), - status); - trigger->trigger->writeUpperLimit(static_cast(scaleFactor * upper), - status); + trigger->trigger->writeLowerLimit( + static_cast(kDutyCycleScaleFactor * lower), status); + trigger->trigger->writeUpperLimit( + static_cast(kDutyCycleScaleFactor * upper), status); } void HAL_SetAnalogTriggerLimitsVoltage( diff --git a/hal/src/main/native/athena/ConstantsInternal.h b/hal/src/main/native/athena/ConstantsInternal.h index 21fece4153..ca7241c731 100644 --- a/hal/src/main/native/athena/ConstantsInternal.h +++ b/hal/src/main/native/athena/ConstantsInternal.h @@ -9,5 +9,6 @@ namespace hal { constexpr int32_t kSystemClockTicksPerMicrosecond = 40; +constexpr int32_t kDutyCycleScaleFactor = 4e7 - 1; } // namespace hal diff --git a/hal/src/main/native/athena/DutyCycle.cpp b/hal/src/main/native/athena/DutyCycle.cpp index 6d70570d30..49f39d9a86 100644 --- a/hal/src/main/native/athena/DutyCycle.cpp +++ b/hal/src/main/native/athena/DutyCycle.cpp @@ -6,6 +6,7 @@ #include +#include "ConstantsInternal.h" #include "DigitalInternal.h" #include "DutyCycleInternal.h" #include "HALInitializer.h" @@ -30,8 +31,6 @@ void InitializeDutyCycle() { } // namespace init } // namespace hal -static constexpr int32_t kScaleFactor = 4e7 - 1; - extern "C" { HAL_DutyCycleHandle HAL_InitializeDutyCycle(HAL_Handle digitalSourceHandle, HAL_AnalogTriggerType triggerType, @@ -90,12 +89,6 @@ int32_t HAL_GetDutyCycleFrequency(HAL_DutyCycleHandle dutyCycleHandle, double HAL_GetDutyCycleOutput(HAL_DutyCycleHandle dutyCycleHandle, int32_t* status) { - return HAL_GetDutyCycleOutputRaw(dutyCycleHandle, status) / - static_cast(kScaleFactor); -} - -int32_t HAL_GetDutyCycleOutputRaw(HAL_DutyCycleHandle dutyCycleHandle, - int32_t* status) { auto dutyCycle = dutyCycleHandles->Get(dutyCycleHandle); if (!dutyCycle) { *status = HAL_HANDLE_ERROR; @@ -104,12 +97,43 @@ int32_t HAL_GetDutyCycleOutputRaw(HAL_DutyCycleHandle dutyCycleHandle, // TODO Handle Overflow unsigned char overflow = 0; - return dutyCycle->dutyCycle->readOutput(&overflow, status); + uint32_t output = dutyCycle->dutyCycle->readOutput(&overflow, status); + return output / static_cast(kDutyCycleScaleFactor); +} + +int32_t HAL_GetDutyCycleHighTime(HAL_DutyCycleHandle dutyCycleHandle, + int32_t* status) { + auto dutyCycle = dutyCycleHandles->Get(dutyCycleHandle); + if (!dutyCycle) { + *status = HAL_HANDLE_ERROR; + return 0; + } + + // TODO Handle Overflow + unsigned char overflow = 0; + uint32_t freq0 = dutyCycle->dutyCycle->readFrequency(&overflow, status); + uint32_t output = dutyCycle->dutyCycle->readOutput(&overflow, status); + uint32_t freq1 = dutyCycle->dutyCycle->readFrequency(&overflow, status); + if (*status != 0) { + return 0; + } + if (freq0 != freq1) { + // Frequency rolled over. Reread output + output = dutyCycle->dutyCycle->readOutput(&overflow, status); + if (*status != 0) { + return 0; + } + } + if (freq1 == 0) { + return 0; + } + // Output will be at max 4e7, so x25 will still fit in a 32 bit signed int. + return (output / freq1) * 25; } int32_t HAL_GetDutyCycleOutputScaleFactor(HAL_DutyCycleHandle dutyCycleHandle, int32_t* status) { - return kScaleFactor; + return kDutyCycleScaleFactor; } int32_t HAL_GetDutyCycleFPGAIndex(HAL_DutyCycleHandle dutyCycleHandle, diff --git a/hal/src/main/native/cpp/jni/DutyCycleJNI.cpp b/hal/src/main/native/cpp/jni/DutyCycleJNI.cpp index 96cc27be9f..f83e13c82c 100644 --- a/hal/src/main/native/cpp/jni/DutyCycleJNI.cpp +++ b/hal/src/main/native/cpp/jni/DutyCycleJNI.cpp @@ -74,15 +74,15 @@ Java_edu_wpi_first_hal_DutyCycleJNI_getOutput /* * Class: edu_wpi_first_hal_DutyCycleJNI - * Method: getOutputRaw + * Method: getHighTime * Signature: (I)I */ JNIEXPORT jint JNICALL -Java_edu_wpi_first_hal_DutyCycleJNI_getOutputRaw +Java_edu_wpi_first_hal_DutyCycleJNI_getHighTime (JNIEnv* env, jclass, jint handle) { int32_t status = 0; - auto retVal = HAL_GetDutyCycleOutputRaw( + auto retVal = HAL_GetDutyCycleHighTime( static_cast(handle), &status); CheckStatus(env, status); return retVal; diff --git a/hal/src/main/native/include/hal/DutyCycle.h b/hal/src/main/native/include/hal/DutyCycle.h index 05b654bc25..90266fd96a 100644 --- a/hal/src/main/native/include/hal/DutyCycle.h +++ b/hal/src/main/native/include/hal/DutyCycle.h @@ -71,24 +71,21 @@ double HAL_GetDutyCycleOutput(HAL_DutyCycleHandle dutyCycleHandle, int32_t* status); /** - * Get the raw output ratio of the duty cycle signal. - * - *

0 means always low, an output equal to - * GetOutputScaleFactor() means always high. + * Get the raw high time of the duty cycle signal. * * @param[in] dutyCycleHandle the duty cycle handle * @param[out] status Error status variable. 0 on success. - * @return output ratio in raw units + * @return high time of last pulse in nanoseconds */ -int32_t HAL_GetDutyCycleOutputRaw(HAL_DutyCycleHandle dutyCycleHandle, - int32_t* status); +int32_t HAL_GetDutyCycleHighTime(HAL_DutyCycleHandle dutyCycleHandle, + int32_t* status); /** * Get the scale factor of the output. * *

An output equal to this value is always high, and then linearly scales - * down to 0. Divide the result of getOutputRaw by this in order to get the - * percentage between 0 and 1. + * 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. diff --git a/hal/src/main/native/sim/DutyCycle.cpp b/hal/src/main/native/sim/DutyCycle.cpp index 51c6506f59..f46d2da6d5 100644 --- a/hal/src/main/native/sim/DutyCycle.cpp +++ b/hal/src/main/native/sim/DutyCycle.cpp @@ -84,6 +84,7 @@ int32_t HAL_GetDutyCycleFrequency(HAL_DutyCycleHandle dutyCycleHandle, } return SimDutyCycleData[dutyCycle->index].frequency; } + double HAL_GetDutyCycleOutput(HAL_DutyCycleHandle dutyCycleHandle, int32_t* status) { auto dutyCycle = dutyCycleHandles->Get(dutyCycleHandle); @@ -93,20 +94,29 @@ double HAL_GetDutyCycleOutput(HAL_DutyCycleHandle dutyCycleHandle, } return SimDutyCycleData[dutyCycle->index].output; } -int32_t HAL_GetDutyCycleOutputRaw(HAL_DutyCycleHandle dutyCycleHandle, - int32_t* status) { + +int32_t HAL_GetDutyCycleHighTime(HAL_DutyCycleHandle dutyCycleHandle, + int32_t* status) { auto dutyCycle = dutyCycleHandles->Get(dutyCycleHandle); if (dutyCycle == nullptr) { *status = HAL_HANDLE_ERROR; return 0; } - return SimDutyCycleData[dutyCycle->index].output * - HAL_GetDutyCycleOutputScaleFactor(dutyCycleHandle, status); + + if (SimDutyCycleData[dutyCycle->index].frequency == 0) { + return 0; + } + + double periodSeconds = 1.0 / SimDutyCycleData[dutyCycle->index].frequency; + double periodNanoSeconds = periodSeconds * 1e9; + return periodNanoSeconds * 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); diff --git a/wpilibc/src/main/native/cpp/DutyCycle.cpp b/wpilibc/src/main/native/cpp/DutyCycle.cpp index a8375e0f16..a244ad65e1 100644 --- a/wpilibc/src/main/native/cpp/DutyCycle.cpp +++ b/wpilibc/src/main/native/cpp/DutyCycle.cpp @@ -73,18 +73,11 @@ double DutyCycle::GetOutput() const { return retVal; } -unsigned int DutyCycle::GetOutputRaw() const { +units::second_t DutyCycle::GetHighTime() const { int32_t status = 0; - auto retVal = HAL_GetDutyCycleOutputRaw(m_handle, &status); + auto retVal = HAL_GetDutyCycleHighTime(m_handle, &status); FRC_CheckErrorStatus(status, "Channel {}", GetSourceChannel()); - return retVal; -} - -unsigned int DutyCycle::GetOutputScaleFactor() const { - int32_t status = 0; - auto retVal = HAL_GetDutyCycleOutputScaleFactor(m_handle, &status); - FRC_CheckErrorStatus(status, "Channel {}", GetSourceChannel()); - return retVal; + return units::nanosecond_t{static_cast(retVal)}; } int DutyCycle::GetSourceChannel() const { diff --git a/wpilibc/src/main/native/include/frc/DutyCycle.h b/wpilibc/src/main/native/include/frc/DutyCycle.h index 7f45d068c1..e2220457fe 100644 --- a/wpilibc/src/main/native/include/frc/DutyCycle.h +++ b/wpilibc/src/main/native/include/frc/DutyCycle.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -83,21 +84,18 @@ class DutyCycle : public wpi::Sendable, public wpi::SendableHelper { double GetOutput() const; /** - * Get the raw output ratio of the duty cycle signal. + * Get the raw high time of the duty cycle signal. * - *

0 means always low, an output equal to - * GetOutputScaleFactor() means always high. - * - * @return output ratio in raw units + * @return high time of last pulse */ - unsigned int GetOutputRaw() const; + units::second_t GetHighTime() const; /** * Get the scale factor of the output. * *

An output equal to this value is always high, and then linearly scales - * down to 0. Divide the result of getOutputRaw by this in order to get the - * percentage between 0 and 1. + * down to 0. Divide a raw result by this in order to get the + * percentage between 0 and 1. Used by DMA. * * @return the output scale factor */ diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycle.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycle.java index 7cd6cba483..d500ba7b45 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycle.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycle.java @@ -73,21 +73,19 @@ public class DutyCycle implements Sendable, AutoCloseable { } /** - * Get the raw output ratio of the duty cycle signal. + * Get the raw high time of the duty cycle signal. * - *

0 means always low, an output equal to getOutputScaleFactor() means always high. - * - * @return output ratio in raw units + * @return high time of last pulse in nanoseconds */ - public int getOutputRaw() { - return DutyCycleJNI.getOutputRaw(m_handle); + public int getHighTimeNanoseconds() { + return DutyCycleJNI.getHighTime(m_handle); } /** * Get the scale factor of the output. * - *

An output equal to this value is always high, and then linearly scales down to 0. Divide the - * result of getOutputRaw by this in order to get the percentage between 0 and 1. + *

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. * * @return the output scale factor */