diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/InterruptableSensorBase.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/InterruptableSensorBase.java index 744e59f1f0..d7a5012df2 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/InterruptableSensorBase.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/InterruptableSensorBase.java @@ -15,6 +15,27 @@ import edu.wpi.first.wpilibj.util.CheckedAllocationException; * Base for sensors to be used with interrupts */ public abstract class InterruptableSensorBase extends SensorBase { + + public static enum WaitResult { + kTimeout(0x0), kRisingEdge(0x1), kFallingEdge(0x100), kBoth(0x101); + + public final int value; + + public static WaitResult valueOf(int value) { + for (WaitResult mode : values()) { + if (mode.value == value) { + return mode; + } + } + return null; + } + + + private WaitResult(int value) { + this.value = value; + } + } + /** * The interrupt resource */ @@ -141,21 +162,25 @@ public abstract class InterruptableSensorBase extends SensorBase { * @param timeout Timeout in seconds * @param ignorePrevious If true, ignore interrupts that happened before * waitForInterrupt was called. + * @return Result of the wait. */ - public void waitForInterrupt(double timeout, boolean ignorePrevious) { + public WaitResult waitForInterrupt(double timeout, boolean ignorePrevious) { if (m_interrupt == 0) { throw new IllegalStateException("The interrupt is not allocated."); } - InterruptJNI.waitForInterrupt(m_interrupt, timeout, ignorePrevious); + int result = InterruptJNI.waitForInterrupt(m_interrupt, timeout, ignorePrevious); + + return WaitResult.valueOf(result); } /** * In synchronous mode, wait for the defined interrupt to occur. * * @param timeout Timeout in seconds + * @return Result of the wait. */ - public void waitForInterrupt(double timeout) { - waitForInterrupt(timeout, true); + public WaitResult waitForInterrupt(double timeout) { + return waitForInterrupt(timeout, true); } /** diff --git a/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AbstractInterruptTest.java b/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AbstractInterruptTest.java index 2ca2931767..4115d705ed 100644 --- a/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AbstractInterruptTest.java +++ b/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AbstractInterruptTest.java @@ -218,6 +218,62 @@ public abstract class AbstractInterruptTest extends AbstractComsSetup { synchronousDelay, interruptRunTime, .1); } + @Test(timeout = (long) (synchronousTimeout * 1e3)) + public void testSynchronousInterruptsWaitResultTimeout() { + // Given + getInterruptable().requestInterrupts(); + + //Don't fire interrupt. Expect it to timeout. + InterruptableSensorBase.WaitResult result = getInterruptable().waitForInterrupt(synchronousTimeout / 2); + + assertEquals("The interrupt did not time out correctly.", result, InterruptableSensorBase.WaitResult.kTimeout); + } + + @Test(timeout = (long) (synchronousTimeout * 1e3)) + public void testSynchronousInterruptsWaitResultRisingEdge() { + // Given + getInterruptable().requestInterrupts(); + + final double synchronousDelay = synchronousTimeout / 2.; + Runnable r = new Runnable() { + @Override + public void run() { + Timer.delay(synchronousDelay); + setInterruptLow(); + setInterruptHigh(); + } + }; + + new Thread(r).start(); + // Delay for twice as long as the timeout so the test should fail first + InterruptableSensorBase.WaitResult result = getInterruptable().waitForInterrupt(synchronousTimeout * 2); + + assertEquals("The interrupt did not fire on the rising edge.", result, InterruptableSensorBase.WaitResult.kRisingEdge); + } + + @Test(timeout = (long) (synchronousTimeout * 1e3)) + public void testSynchronousInterruptsWaitResultFallingEdge() { + // Given + getInterruptable().requestInterrupts(); + getInterruptable().setUpSourceEdge(false, true); + + final double synchronousDelay = synchronousTimeout / 2.; + Runnable r = new Runnable() { + @Override + public void run() { + Timer.delay(synchronousDelay); + setInterruptHigh(); + setInterruptLow(); + } + }; + + new Thread(r).start(); + // Delay for twice as long as the timeout so the test should fail first + InterruptableSensorBase.WaitResult result = getInterruptable().waitForInterrupt(synchronousTimeout * 2); + + assertEquals("The interrupt did not fire on the falling edge.", result, InterruptableSensorBase.WaitResult.kFallingEdge); + } + @Test(timeout = 4000) public void testDisableStopsInterruptFiring() {