mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-03 03:01:44 +00:00
[wpilibj] Fix java async interrupts (#3559)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
45
wpilibc/src/test/native/cpp/InterruptTest.cpp
Normal file
45
wpilibc/src/test/native/cpp/InterruptTest.cpp
Normal 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
|
||||
@@ -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. */
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user