[wpilibj] Fix java async interrupts (#3559)

This commit is contained in:
Thad House
2021-09-11 09:21:02 -07:00
committed by GitHub
parent 5e6c34c61c
commit d8e0b6c977
4 changed files with 102 additions and 6 deletions

View File

@@ -121,16 +121,18 @@ static void ProcessInterruptDigitalSynchronous(const char* name, void* param,
return;
}
bool retVal = value->data.v_boolean;
auto previousState = interrupt->previousState;
interrupt->previousState = retVal;
// If no change in interrupt, return;
if (retVal == interrupt->previousState) {
if (retVal == previousState) {
return;
}
// If its a falling change, and we dont fire on falling return
if (interrupt->previousState && !interrupt->fireOnDown) {
if (previousState && !interrupt->fireOnDown) {
return;
}
// If its a rising change, and we dont fire on rising return.
if (!interrupt->previousState && !interrupt->fireOnUp) {
if (!previousState && !interrupt->fireOnUp) {
return;
}
@@ -174,16 +176,18 @@ static void ProcessInterruptAnalogSynchronous(const char* name, void* param,
// Pulse interrupt
interruptData->waitCond.notify_all();
}
auto previousState = interrupt->previousState;
interrupt->previousState = retVal;
// If no change in interrupt, return;
if (retVal == interrupt->previousState) {
if (retVal == previousState) {
return;
}
// If its a falling change, and we dont fire on falling return
if (interrupt->previousState && !interrupt->fireOnDown) {
if (previousState && !interrupt->fireOnDown) {
return;
}
// If its a rising change, and we dont fire on rising return.
if (!interrupt->previousState && !interrupt->fireOnUp) {
if (!previousState && !interrupt->fireOnUp) {
return;
}

View File

@@ -0,0 +1,45 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <atomic>
#include <hal/HAL.h>
#include "frc/AsynchronousInterrupt.h"
#include "frc/DigitalInput.h"
#include "frc/Timer.h"
#include "frc/simulation/DIOSim.h"
#include "gtest/gtest.h"
namespace frc {
using namespace frc::sim;
TEST(InterruptTest, AsynchronousInterrupt) {
HAL_Initialize(500, 0);
std::atomic_int counter{0};
std::atomic_bool hasFired{false};
DigitalInput di{0};
AsynchronousInterrupt interrupt{di, [&](bool rising, bool falling) {
counter++;
hasFired = true;
}};
interrupt.Enable();
frc::Wait(0.5_s);
DIOSim digitalSim{di};
digitalSim.SetValue(false);
frc::Wait(20_ms);
digitalSim.SetValue(true);
frc::Wait(10_ms);
int count = 0;
while (!hasFired) {
frc::Wait(5_ms);
count++;
ASSERT_TRUE(count < 1000);
}
ASSERT_EQ(1, counter.load());
}
} // namespace frc

View File

@@ -66,6 +66,7 @@ public class AsynchronousInterrupt implements AutoCloseable {
m_keepRunning.set(true);
m_thread = new Thread(this::threadMain);
m_thread.start();
}
/** Disables interrupt callbacks. Does nothing if already disabled. */

View File

@@ -0,0 +1,46 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.wpilibj;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import edu.wpi.first.wpilibj.simulation.DIOSim;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Test;
public class InterruptTest {
@Test
void testAsynchronousInterrupt() {
AtomicBoolean hasFired = new AtomicBoolean(false);
AtomicInteger counter = new AtomicInteger(0);
try (DigitalInput di = new DigitalInput(0);
AsynchronousInterrupt interrupt =
new AsynchronousInterrupt(
di,
(a, b) -> {
counter.incrementAndGet();
hasFired.set(true);
})) {
interrupt.enable();
Timer.delay(0.5);
DIOSim digitalSim = new DIOSim(di);
digitalSim.setValue(false);
Timer.delay(0.01);
digitalSim.setValue(true);
Timer.delay(0.01);
int count = 0;
while (!hasFired.get()) {
Timer.delay(0.005);
count++;
assertTrue(count < 1000);
}
assertEquals(1, counter.get(), "The interrupt did not fire the expected number of times");
}
}
}