diff --git a/hal/src/main/java/edu/wpi/first/hal/DIOJNI.java b/hal/src/main/java/edu/wpi/first/hal/DIOJNI.java index ed8e86fdf8..689a95e7f8 100644 --- a/hal/src/main/java/edu/wpi/first/hal/DIOJNI.java +++ b/hal/src/main/java/edu/wpi/first/hal/DIOJNI.java @@ -39,5 +39,7 @@ public class DIOJNI extends JNIWrapper { public static native void setDigitalPWMDutyCycle(int pwmGenerator, double dutyCycle); + public static native void setDigitalPWMPPS(int pwmGenerator, double dutyCycle); + public static native void setDigitalPWMOutputChannel(int pwmGenerator, int channel); } diff --git a/hal/src/main/native/athena/DIO.cpp b/hal/src/main/native/athena/DIO.cpp index 01437043aa..e6308fbb75 100644 --- a/hal/src/main/native/athena/DIO.cpp +++ b/hal/src/main/native/athena/DIO.cpp @@ -240,6 +240,30 @@ void HAL_SetDigitalPWMDutyCycle(HAL_DigitalPWMHandle pwmGenerator, } } +void HAL_SetDigitalPWMPPS(HAL_DigitalPWMHandle pwmGenerator, double dutyCycle, + int32_t* status) { + auto port = digitalPWMHandles->Get(pwmGenerator); + if (port == nullptr) { + *status = HAL_HANDLE_ERROR; + return; + } + int32_t id = *port; + digitalSystem->writePWMPeriodPower(0xffff, status); + double rawDutyCycle = 31.0 * dutyCycle; + if (rawDutyCycle > 30.5) { + rawDutyCycle = 30.5; + } + { + std::scoped_lock lock(digitalPwmMutex); + if (id < 4) + digitalSystem->writePWMDutyCycleA(id, static_cast(rawDutyCycle), + status); + else + digitalSystem->writePWMDutyCycleB( + id - 4, static_cast(rawDutyCycle), status); + } +} + void HAL_SetDigitalPWMOutputChannel(HAL_DigitalPWMHandle pwmGenerator, int32_t channel, int32_t* status) { auto port = digitalPWMHandles->Get(pwmGenerator); diff --git a/hal/src/main/native/cpp/jni/DIOJNI.cpp b/hal/src/main/native/cpp/jni/DIOJNI.cpp index 264a347ac6..dee34c7f46 100644 --- a/hal/src/main/native/cpp/jni/DIOJNI.cpp +++ b/hal/src/main/native/cpp/jni/DIOJNI.cpp @@ -260,6 +260,20 @@ Java_edu_wpi_first_hal_DIOJNI_setDigitalPWMDutyCycle CheckStatus(env, status); } +/* + * Class: edu_wpi_first_hal_DIOJNI + * Method: setDigitalPWMPPS + * Signature: (ID)V + */ +JNIEXPORT void JNICALL +Java_edu_wpi_first_hal_DIOJNI_setDigitalPWMPPS + (JNIEnv* env, jclass, jint id, jdouble value) +{ + int32_t status = 0; + HAL_SetDigitalPWMPPS((HAL_DigitalPWMHandle)id, value, &status); + CheckStatus(env, status); +} + /* * Class: edu_wpi_first_hal_DIOJNI * Method: setDigitalPWMOutputChannel diff --git a/hal/src/main/native/include/hal/DIO.h b/hal/src/main/native/include/hal/DIO.h index e6a703b16c..ab53321177 100644 --- a/hal/src/main/native/include/hal/DIO.h +++ b/hal/src/main/native/include/hal/DIO.h @@ -94,6 +94,16 @@ void HAL_SetDigitalPWMRate(double rate, int32_t* status); void HAL_SetDigitalPWMDutyCycle(HAL_DigitalPWMHandle pwmGenerator, double dutyCycle, int32_t* status); +/** + * Configures the digital PWM to be a PPS signal with specified duty cycle. + * + * @param[in] pwmGenerator the digital PWM handle + * @param[in] dutyCycle the percent duty cycle to output [0..1] + * @param[out] status Error status variable. 0 on success. + */ +void HAL_SetDigitalPWMPPS(HAL_DigitalPWMHandle pwmGenerator, double dutyCycle, + int32_t* status); + /** * Configures which DO channel the PWM signal is output on. * diff --git a/hal/src/main/native/sim/DIO.cpp b/hal/src/main/native/sim/DIO.cpp index 53c700cb2d..b611b35e8a 100644 --- a/hal/src/main/native/sim/DIO.cpp +++ b/hal/src/main/native/sim/DIO.cpp @@ -151,6 +151,23 @@ void HAL_SetDigitalPWMDutyCycle(HAL_DigitalPWMHandle pwmGenerator, SimDigitalPWMData[id].dutyCycle = dutyCycle; } +void HAL_SetDigitalPWMPPS(HAL_DigitalPWMHandle pwmGenerator, double dutyCycle, + int32_t* status) { + auto port = digitalPWMHandles->Get(pwmGenerator); + if (port == nullptr) { + *status = HAL_HANDLE_ERROR; + return; + } + int32_t id = *port; + if (dutyCycle > 1.0) { + dutyCycle = 1.0; + } + if (dutyCycle < 0.0) { + dutyCycle = 0.0; + } + SimDigitalPWMData[id].dutyCycle = dutyCycle; +} + void HAL_SetDigitalPWMOutputChannel(HAL_DigitalPWMHandle pwmGenerator, int32_t channel, int32_t* status) { auto port = digitalPWMHandles->Get(pwmGenerator); diff --git a/wpilibc/src/main/native/include/frc/DigitalOutput.h b/wpilibc/src/main/native/include/frc/DigitalOutput.h index 073f1568b6..d2981face0 100644 --- a/wpilibc/src/main/native/include/frc/DigitalOutput.h +++ b/wpilibc/src/main/native/include/frc/DigitalOutput.h @@ -105,6 +105,19 @@ class DigitalOutput : public DigitalSource, */ void SetPWMRate(double rate); + /** + * Enable a PWM PPS (Pulse Per Second) Output on this line. + * + * Allocate one of the 6 DO PWM generator resources from this module. + * + * Supply the duty-cycle to output. + * + * The resolution of the duty cycle is 8-bit. + * + * @param dutyCycle The duty-cycle to start generating. [0..1] + */ + void EnablePPS(double dutyCycle); + /** * Enable a PWM Output on this line. * diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalOutput.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalOutput.java index 1859d9318b..43af5c7b69 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalOutput.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalOutput.java @@ -113,6 +113,26 @@ public class DigitalOutput extends DigitalSource implements Sendable { DIOJNI.setDigitalPWMRate(rate); } + /** + * Enable a PWM PPS (Pulse Per Second) Output on this line. + * + *

Allocate one of the 6 DO PWM generator resources. + * + *

Supply the duty-cycle to output. + * + *

The resolution of the duty cycle is 8-bit. + * + * @param dutyCycle The duty-cycle to start generating. [0..1] + */ + public void enablePPS(double dutyCycle) { + if (m_pwmGenerator != invalidPwmGenerator) { + return; + } + m_pwmGenerator = DIOJNI.allocateDigitalPWM(); + DIOJNI.setDigitalPWMPPS(m_pwmGenerator, dutyCycle); + DIOJNI.setDigitalPWMOutputChannel(m_pwmGenerator, m_channel); + } + /** * Enable a PWM Output on this line. *