diff --git a/wpilibcIntegrationTests/src/DIOLoopTest.cpp b/wpilibcIntegrationTests/src/DIOLoopTest.cpp index c13d1450f5..e5fe4fad3b 100644 --- a/wpilibcIntegrationTests/src/DIOLoopTest.cpp +++ b/wpilibcIntegrationTests/src/DIOLoopTest.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "gtest/gtest.h" #include "TestBench.h" @@ -58,6 +59,60 @@ TEST_F(DIOLoopTest, Loop) { EXPECT_TRUE(m_input->Get()) << "The digital output was turned on, but " << "the digital input is off."; } +/** + * Tests to see if the DIO PWM functionality works. + */ +TEST_F(DIOLoopTest, DIOPWM) { + Reset(); + + m_output->Set(false); + Wait(kDelayTime); + EXPECT_FALSE(m_input->Get()) << "The digital output was turned off, but " + << "the digital input is on."; + + //Set frequency to 2.0 Hz + m_output->SetPWMRate(2.0); + //Enable PWM, but leave it off + m_output->EnablePWM(0.0); + Wait(0.5); + m_output->UpdateDutyCycle(0.5); + m_input->RequestInterrupts(); + m_input->SetUpSourceEdge(false, true); + InterruptableSensorBase::WaitResult result = m_input->WaitForInterrupt(3.0, true); + + Wait(0.5); + bool firstCycle = m_input->Get(); + Wait(0.5); + bool secondCycle = m_input->Get(); + Wait(0.5); + bool thirdCycle = m_input->Get(); + Wait(0.5); + bool forthCycle = m_input->Get(); + Wait(0.5); + bool fifthCycle = m_input->Get(); + Wait(0.5); + bool sixthCycle = m_input->Get(); + Wait(0.5); + bool seventhCycle = m_input->Get(); + m_output->DisablePWM(); + Wait(0.5); + bool firstAfterStop = m_input->Get(); + Wait(0.5); + bool secondAfterStop = m_input->Get(); + + EXPECT_EQ(InterruptableSensorBase::WaitResult::kFallingEdge, result) + << "WaitForInterrupt was not falling."; + + EXPECT_FALSE(firstCycle) << "Input not low after first delay"; + EXPECT_TRUE(secondCycle) << "Input not high after second delay"; + EXPECT_FALSE(thirdCycle) << "Input not low after third delay"; + EXPECT_TRUE(forthCycle) << "Input not high after forth delay"; + EXPECT_FALSE(fifthCycle) << "Input not low after fifth delay"; + EXPECT_TRUE(sixthCycle) << "Input not high after sixth delay"; + EXPECT_FALSE(seventhCycle) << "Input not low after seventh delay"; + EXPECT_FALSE(firstAfterStop) << "Input not low after stopping first read"; + EXPECT_FALSE(secondAfterStop) << "Input not low after stopping second read"; +} /** * Test a fake "counter" that uses the DIO loop as an input to make sure the diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalOutput.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalOutput.java index 50a0a6f0af..7dc744e23f 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalOutput.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DigitalOutput.java @@ -22,7 +22,9 @@ import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tReso */ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { - private long m_pwmGenerator; + private static final long invalidPwmGenerator = 0xffffffff; + + private long m_pwmGenerator = invalidPwmGenerator; /** * Create an instance of a digital output. Create an instance of a digital @@ -43,7 +45,7 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { @Override public void free() { // disable the pwm only if we have allocated it - if (m_pwmGenerator != 0) { + if (m_pwmGenerator != invalidPwmGenerator) { disablePWM(); } super.free(); @@ -131,7 +133,7 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { * @param initialDutyCycle The duty-cycle to start generating. [0..1] */ public void enablePWM(double initialDutyCycle) { - if (m_pwmGenerator != 0) + if (m_pwmGenerator != invalidPwmGenerator) return; m_pwmGenerator = PWMJNI.allocatePWM(); PWMJNI.setPWMDutyCycle(m_pwmGenerator, initialDutyCycle); @@ -144,7 +146,7 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { * Free up one of the 6 DO PWM generator resources that were in use. */ public void disablePWM() { - if (m_pwmGenerator == 0) + if (m_pwmGenerator == invalidPwmGenerator) return; // Disable the output by routing to a dead bit. PWMJNI.setPWMOutputChannel(m_pwmGenerator, kDigitalChannels); @@ -161,7 +163,7 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable { * @param dutyCycle The duty-cycle to change to. [0..1] */ public void updateDutyCycle(double dutyCycle) { - if (m_pwmGenerator == 0) + if (m_pwmGenerator == invalidPwmGenerator) return; PWMJNI.setPWMDutyCycle(m_pwmGenerator, dutyCycle); } diff --git a/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DIOCrossConnectTest.java b/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DIOCrossConnectTest.java index 83da79d5c0..099911631f 100644 --- a/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DIOCrossConnectTest.java +++ b/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DIOCrossConnectTest.java @@ -107,6 +107,54 @@ public class DIOCrossConnectTest extends AbstractInterruptTest { assertFalse("DIO Not Low after .05s delay", dio.getInput().get()); } + /** + * Tests to see if the DIO PWM functionality works. + */ + @Test + public void testDIOPWM() { + dio.getOutput().set(false); + assertFalse("DIO Not Low after no delay", dio.getInput().get()); + //Set frequency to 2.0 Hz + dio.getOutput().setPWMRate(2.0); + //Enable PWM, but leave it off. + dio.getOutput().enablePWM(0.0); + Timer.delay(0.5); + dio.getOutput().updateDutyCycle(0.5); + dio.getInput().requestInterrupts(); + dio.getInput().setUpSourceEdge(false, true); + //TODO: Add return value from WaitForInterrupt + dio.getInput().waitForInterrupt(3.0, true); + Timer.delay(0.5); + boolean firstCycle = dio.getInput().get(); + Timer.delay(0.5); + boolean secondCycle = dio.getInput().get(); + Timer.delay(0.5); + boolean thirdCycle = dio.getInput().get(); + Timer.delay(0.5); + boolean forthCycle = dio.getInput().get(); + Timer.delay(0.5); + boolean fifthCycle = dio.getInput().get(); + Timer.delay(0.5); + boolean sixthCycle = dio.getInput().get(); + Timer.delay(0.5); + boolean seventhCycle = dio.getInput().get(); + dio.getOutput().disablePWM(); + Timer.delay(0.5); + boolean firstAfterStop = dio.getInput().get(); + Timer.delay(0.5); + boolean secondAfterStop = dio.getInput().get(); + + assertFalse("DIO Not Low after first delay", firstCycle); + assertTrue("DIO Not High after second delay", secondCycle); + assertFalse("DIO Not Low after third delay", thirdCycle); + assertTrue("DIO Not High after forth delay", forthCycle); + assertFalse("DIO Not Low after fifth delay", fifthCycle); + assertTrue("DIO Not High after sixth delay", sixthCycle); + assertFalse("DIO Not Low after seventh delay", seventhCycle); + assertFalse("DIO Not Low after stopping first read", firstAfterStop); + assertFalse("DIO Not Low after stopping second read", secondAfterStop); + } + /* * (non-Javadoc) *$