[hal, wpilib] Remove DigitalSource and AnalogTrigger (#7753)

This commit is contained in:
Thad House
2025-01-30 18:58:21 -08:00
committed by GitHub
parent 7533b323d1
commit 6e704370b3
63 changed files with 7 additions and 2994 deletions

View File

@@ -1,198 +0,0 @@
// 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 edu.wpi.first.hal.AnalogJNI;
import edu.wpi.first.hal.FRCNetComm.tResourceType;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.hal.util.BoundaryException;
import edu.wpi.first.util.sendable.Sendable;
import edu.wpi.first.util.sendable.SendableBuilder;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.AnalogTriggerOutput.AnalogTriggerType;
import java.lang.ref.Reference;
/** Class for creating and configuring Analog Triggers. */
public class AnalogTrigger implements Sendable, AutoCloseable {
/** Where the analog trigger is attached. */
protected int m_port;
private AnalogInput m_analogInput;
private DutyCycle m_dutyCycle;
private boolean m_ownsAnalog;
/**
* Constructor for an analog trigger given a channel number.
*
* @param channel the port to use for the analog trigger
*/
@SuppressWarnings("this-escape")
public AnalogTrigger(final int channel) {
this(new AnalogInput(channel));
m_ownsAnalog = true;
SendableRegistry.addChild(this, m_analogInput);
}
/**
* Construct an analog trigger given an analog channel. This should be used in the case of sharing
* an analog channel between the trigger and an analog input object.
*
* @param channel the AnalogInput to use for the analog trigger
*/
@SuppressWarnings("this-escape")
public AnalogTrigger(AnalogInput channel) {
m_analogInput = channel;
m_port = AnalogJNI.initializeAnalogTrigger(channel.m_port);
int index = getIndex();
HAL.report(tResourceType.kResourceType_AnalogTrigger, index + 1);
SendableRegistry.add(this, "AnalogTrigger", index);
}
/**
* Construct an analog trigger given a duty cycle input.
*
* @param input the DutyCycle to use for the analog trigger
*/
@SuppressWarnings("this-escape")
public AnalogTrigger(DutyCycle input) {
m_dutyCycle = input;
m_port = AnalogJNI.initializeAnalogTriggerDutyCycle(input.m_handle);
int index = getIndex();
HAL.report(tResourceType.kResourceType_AnalogTrigger, index + 1);
SendableRegistry.add(this, "AnalogTrigger", index);
}
@Override
public void close() {
try {
SendableRegistry.remove(this);
AnalogJNI.cleanAnalogTrigger(m_port);
m_port = 0;
if (m_ownsAnalog && m_analogInput != null) {
m_analogInput.close();
}
} finally {
Reference.reachabilityFence(m_dutyCycle);
}
}
/**
* Set the upper and lower limits of the analog trigger. The limits are given in ADC codes. If
* oversampling is used, the units must be scaled appropriately.
*
* @param lower the lower raw limit
* @param upper the upper raw limit
*/
public void setLimitsRaw(final int lower, final int upper) {
if (lower > upper) {
throw new BoundaryException("Lower bound is greater than upper");
}
AnalogJNI.setAnalogTriggerLimitsRaw(m_port, lower, upper);
}
/**
* Set the upper and lower limits of the analog trigger. The limits are given as floating point
* values between 0 and 1.
*
* @param lower the lower duty cycle limit
* @param upper the upper duty cycle limit
*/
public void setLimitsDutyCycle(double lower, double upper) {
if (lower > upper) {
throw new BoundaryException("Lower bound is greater than upper bound");
}
AnalogJNI.setAnalogTriggerLimitsDutyCycle(m_port, lower, upper);
}
/**
* Set the upper and lower limits of the analog trigger. The limits are given as floating point
* voltage values.
*
* @param lower the lower voltage limit
* @param upper the upper voltage limit
*/
public void setLimitsVoltage(double lower, double upper) {
if (lower > upper) {
throw new BoundaryException("Lower bound is greater than upper bound");
}
AnalogJNI.setAnalogTriggerLimitsVoltage(m_port, lower, upper);
}
/**
* Configure the analog trigger to use the averaged vs. raw values. If the value is true, then the
* averaged value is selected for the analog trigger, otherwise the immediate value is used.
*
* @param useAveragedValue true to use an averaged value, false otherwise
*/
public void setAveraged(boolean useAveragedValue) {
AnalogJNI.setAnalogTriggerAveraged(m_port, useAveragedValue);
}
/**
* Configure the analog trigger to use a filtered value. The analog trigger will operate with a 3
* point average rejection filter. This is designed to help with 360 degree pot applications for
* the period where the pot crosses through zero.
*
* @param useFilteredValue true to use a filtered value, false otherwise
*/
public void setFiltered(boolean useFilteredValue) {
AnalogJNI.setAnalogTriggerFiltered(m_port, useFilteredValue);
}
/**
* Return the index of the analog trigger. This is the FPGA index of this analog trigger instance.
*
* @return The index of the analog trigger.
*/
public final int getIndex() {
return AnalogJNI.getAnalogTriggerFPGAIndex(m_port);
}
/**
* Return the InWindow output of the analog trigger. True if the analog input is between the upper
* and lower limits.
*
* @return The InWindow output of the analog trigger.
*/
public boolean getInWindow() {
return AnalogJNI.getAnalogTriggerInWindow(m_port);
}
/**
* Return the TriggerState output of the analog trigger. True if above upper limit. False if below
* lower limit. If in Hysteresis, maintain previous state.
*
* @return The TriggerState output of the analog trigger.
*/
public boolean getTriggerState() {
return AnalogJNI.getAnalogTriggerTriggerState(m_port);
}
/**
* Creates an AnalogTriggerOutput object. Gets an output object that can be used for routing.
* Caller is responsible for deleting the AnalogTriggerOutput object.
*
* @param type An enum of the type of output object to create.
* @return A pointer to a new AnalogTriggerOutput object.
*/
public AnalogTriggerOutput createOutput(AnalogTriggerType type) {
return new AnalogTriggerOutput(this, type);
}
@Override
public void initSendable(SendableBuilder builder) {
if (m_ownsAnalog) {
m_analogInput.initSendable(builder);
}
}
}

View File

@@ -1,127 +0,0 @@
// 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 edu.wpi.first.util.ErrorMessages.requireNonNullParam;
import edu.wpi.first.hal.AnalogJNI;
import edu.wpi.first.hal.FRCNetComm.tResourceType;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.util.sendable.Sendable;
import edu.wpi.first.util.sendable.SendableBuilder;
/**
* Class to represent a specific output from an analog trigger. This class is used to get the
* current output value and also as a DigitalSource to provide routing of an output to digital
* subsystems on the FPGA such as Counter, Encoder, and Interrupt.
*
* <p>The TriggerState output indicates the primary output value of the trigger. If the analog
* signal is less than the lower limit, the output is false. If the analog value is greater than the
* upper limit, then the output is true. If the analog value is in between, then the trigger output
* state maintains its most recent value.
*
* <p>The InWindow output indicates whether the analog signal is inside the range defined by the
* limits.
*
* <p>The RisingPulse and FallingPulse outputs detect an instantaneous transition from above the
* upper limit to below the lower limit, and vice versa. These pulses represent a rollover condition
* of a sensor and can be routed to an up / down counter or to interrupts. Because the outputs
* generate a pulse, they cannot be read directly. To help ensure that a rollover condition is not
* missed, there is an average rejection filter available that operates on the upper 8 bits of a 12
* bit number and selects the nearest outlier of 3 samples. This will reject a sample that is (due
* to averaging or sampling) errantly between the two limits. This filter will fail if more than one
* sample in a row is errantly in between the two limits. You may see this problem if attempting to
* use this feature with a mechanical rollover sensor, such as a 360 degree no-stop potentiometer
* without signal conditioning, because the rollover transition is not sharp / clean enough. Using
* the averaging engine may help with this, but rotational speeds of the sensor will then be
* limited.
*/
public class AnalogTriggerOutput extends DigitalSource implements Sendable {
/** Exceptions dealing with improper operation of the Analog trigger output. */
public static class AnalogTriggerOutputException extends RuntimeException {
/**
* Create a new exception with the given message.
*
* @param message the message to pass with the exception
*/
public AnalogTriggerOutputException(String message) {
super(message);
}
}
private final AnalogTrigger m_trigger;
private final AnalogTriggerType m_outputType;
/**
* Create an object that represents one of the four outputs from an analog trigger.
*
* <p>Because this class derives from DigitalSource, it can be passed into routing functions for
* Counter, Encoder, etc.
*
* @param trigger The trigger for which this is an output.
* @param outputType An enum that specifies the output on the trigger to represent.
*/
public AnalogTriggerOutput(AnalogTrigger trigger, final AnalogTriggerType outputType) {
requireNonNullParam(trigger, "trigger", "AnalogTriggerOutput");
requireNonNullParam(outputType, "outputType", "AnalogTriggerOutput");
m_trigger = trigger;
m_outputType = outputType;
HAL.report(
tResourceType.kResourceType_AnalogTriggerOutput,
trigger.getIndex() + 1,
outputType.value + 1);
}
/**
* Get the state of the analog trigger output.
*
* @return The state of the analog trigger output.
*/
public boolean get() {
return AnalogJNI.getAnalogTriggerOutput(m_trigger.m_port, m_outputType.value);
}
@Override
public int getPortHandleForRouting() {
return m_trigger.m_port;
}
@Override
public int getAnalogTriggerTypeForRouting() {
return m_outputType.value;
}
@Override
public int getChannel() {
return m_trigger.getIndex();
}
@Override
public boolean isAnalogTrigger() {
return true;
}
/** Defines the state in which the AnalogTrigger triggers. */
public enum AnalogTriggerType {
/** In window. */
kInWindow(AnalogJNI.AnalogTriggerType.kInWindow),
/** State. */
kState(AnalogJNI.AnalogTriggerType.kState),
/** Rising pulse. */
kRisingPulse(AnalogJNI.AnalogTriggerType.kRisingPulse),
/** Falling pulse. */
kFallingPulse(AnalogJNI.AnalogTriggerType.kFallingPulse);
private final int value;
AnalogTriggerType(int value) {
this.value = value;
}
}
@Override
public void initSendable(SendableBuilder builder) {}
}

View File

@@ -18,7 +18,7 @@ import edu.wpi.first.util.sendable.SendableRegistry;
* elsewhere will automatically allocate digital inputs and outputs as required. This class is only
* for devices like switches etc. that aren't implemented anywhere else.
*/
public class DigitalInput extends DigitalSource implements Sendable {
public class DigitalInput implements AutoCloseable, Sendable {
private final int m_channel;
private int m_handle;
@@ -40,7 +40,6 @@ public class DigitalInput extends DigitalSource implements Sendable {
@Override
public void close() {
super.close();
SendableRegistry.remove(this);
DIOJNI.freeDIOPort(m_handle);
m_handle = 0;
@@ -61,41 +60,10 @@ public class DigitalInput extends DigitalSource implements Sendable {
*
* @return The GPIO channel number that this object represents.
*/
@Override
public int getChannel() {
return m_channel;
}
/**
* Get the analog trigger type.
*
* @return false
*/
@Override
public int getAnalogTriggerTypeForRouting() {
return 0;
}
/**
* Is this an analog trigger.
*
* @return true if this is an analog trigger
*/
@Override
public boolean isAnalogTrigger() {
return false;
}
/**
* Get the HAL Port Handle.
*
* @return The HAL Handle to the specified source.
*/
@Override
public int getPortHandleForRouting() {
return m_handle;
}
/**
* Indicates this input is used by a simulated device.
*

View File

@@ -16,7 +16,7 @@ import edu.wpi.first.util.sendable.SendableRegistry;
* Class to write digital outputs. This class will write digital outputs. Other devices that are
* implemented elsewhere will automatically allocate digital inputs and outputs as required.
*/
public class DigitalOutput extends DigitalSource implements Sendable {
public class DigitalOutput implements AutoCloseable, Sendable {
private static final int invalidPwmGenerator = 0;
private int m_pwmGenerator = invalidPwmGenerator;
@@ -42,7 +42,6 @@ public class DigitalOutput extends DigitalSource implements Sendable {
@Override
public void close() {
super.close();
SendableRegistry.remove(this);
// Disable the pwm only if we have allocated it
if (m_pwmGenerator != invalidPwmGenerator) {
@@ -75,7 +74,6 @@ public class DigitalOutput extends DigitalSource implements Sendable {
*
* @return The GPIO channel number.
*/
@Override
public int getChannel() {
return m_channel;
}
@@ -199,34 +197,4 @@ public class DigitalOutput extends DigitalSource implements Sendable {
builder.setSmartDashboardType("Digital Output");
builder.addBooleanProperty("Value", this::get, this::set);
}
/**
* Is this an analog trigger.
*
* @return true if this is an analog trigger
*/
@Override
public boolean isAnalogTrigger() {
return false;
}
/**
* Get the analog trigger type.
*
* @return false
*/
@Override
public int getAnalogTriggerTypeForRouting() {
return 0;
}
/**
* Get the HAL Port Handle.
*
* @return The HAL Handle to the specified source.
*/
@Override
public int getPortHandleForRouting() {
return m_handle;
}
}

View File

@@ -1,47 +0,0 @@
// 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;
/**
* DigitalSource Interface. The DigitalSource represents all the possible inputs for a counter or a
* quadrature encoder. The source may be either a digital input or an analog input. If the caller
* just provides a channel, then a digital input will be constructed and freed when finished for the
* source. The source can either be a digital input or analog trigger but not both.
*/
public abstract class DigitalSource implements AutoCloseable {
/** Default constructor. */
public DigitalSource() {}
/**
* Returns true if this DigitalSource is an AnalogTrigger.
*
* @return True if this DigitalSource is an AnalogTrigger.
*/
public abstract boolean isAnalogTrigger();
/**
* The DigitalSource channel.
*
* @return The DigitalSource channel.
*/
public abstract int getChannel();
/**
* If this is an analog trigger.
*
* @return true if this is an analog trigger.
*/
public abstract int getAnalogTriggerTypeForRouting();
/**
* The channel routing number.
*
* @return channel routing number
*/
public abstract int getPortHandleForRouting();
@Override
public void close() {}
}

View File

@@ -15,7 +15,7 @@ import edu.wpi.first.util.sendable.SendableRegistry;
* Class to read a duty cycle PWM input.
*
* <p>PWM input signals are specified with a frequency and a ratio of high to low in that frequency.
* There are 8 of these in the roboRIO, and they can be attached to any {@link DigitalSource}.
* There are 8 of these in the roboRIO, and they can be attached to any SmartIO Channel.
*
* <p>These can be combined as the input of an AnalogTrigger to a Counter in order to implement
* rollover checking.

View File

@@ -1,153 +0,0 @@
// 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.simulation;
import edu.wpi.first.hal.simulation.AnalogTriggerDataJNI;
import edu.wpi.first.hal.simulation.NotifyCallback;
import edu.wpi.first.wpilibj.AnalogTrigger;
import java.util.NoSuchElementException;
/** Class to control a simulated analog trigger. */
public class AnalogTriggerSim {
private final int m_index;
/**
* Constructs from an AnalogTrigger object.
*
* @param analogTrigger AnalogTrigger to simulate
*/
public AnalogTriggerSim(AnalogTrigger analogTrigger) {
m_index = analogTrigger.getIndex();
}
private AnalogTriggerSim(int index) {
m_index = index;
}
/**
* Creates an AnalogTriggerSim for an analog input channel.
*
* @param channel analog input channel
* @return Simulated object
* @throws NoSuchElementException if no AnalogTrigger is configured for that channel
*/
public static AnalogTriggerSim createForChannel(int channel) {
int index = AnalogTriggerDataJNI.findForChannel(channel);
if (index < 0) {
throw new NoSuchElementException("no analog trigger found for channel " + channel);
}
return new AnalogTriggerSim(index);
}
/**
* Creates an AnalogTriggerSim for a simulated index. The index is incremented for each simulated
* AnalogTrigger.
*
* @param index simulator index
* @return Simulated object
*/
public static AnalogTriggerSim createForIndex(int index) {
return new AnalogTriggerSim(index);
}
/**
* Register a callback on whether the analog trigger is initialized.
*
* @param callback the callback that will be called whenever the analog trigger is initialized
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback.
*/
public CallbackStore registerInitializedCallback(NotifyCallback callback, boolean initialNotify) {
int uid = AnalogTriggerDataJNI.registerInitializedCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogTriggerDataJNI::cancelInitializedCallback);
}
/**
* Check if this analog trigger has been initialized.
*
* @return true if initialized
*/
public boolean getInitialized() {
return AnalogTriggerDataJNI.getInitialized(m_index);
}
/**
* Change whether this analog trigger has been initialized.
*
* @param initialized the new value
*/
public void setInitialized(boolean initialized) {
AnalogTriggerDataJNI.setInitialized(m_index, initialized);
}
/**
* Register a callback on the lower bound.
*
* @param callback the callback that will be called whenever the lower bound is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback.
*/
public CallbackStore registerTriggerLowerBoundCallback(
NotifyCallback callback, boolean initialNotify) {
int uid =
AnalogTriggerDataJNI.registerTriggerLowerBoundCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogTriggerDataJNI::cancelTriggerLowerBoundCallback);
}
/**
* Get the lower bound.
*
* @return the lower bound
*/
public double getTriggerLowerBound() {
return AnalogTriggerDataJNI.getTriggerLowerBound(m_index);
}
/**
* Change the lower bound.
*
* @param triggerLowerBound the new lower bound
*/
public void setTriggerLowerBound(double triggerLowerBound) {
AnalogTriggerDataJNI.setTriggerLowerBound(m_index, triggerLowerBound);
}
/**
* Register a callback on the upper bound.
*
* @param callback the callback that will be called whenever the upper bound is changed
* @param initialNotify if true, the callback will be run on the initial value
* @return the {@link CallbackStore} object associated with this callback.
*/
public CallbackStore registerTriggerUpperBoundCallback(
NotifyCallback callback, boolean initialNotify) {
int uid =
AnalogTriggerDataJNI.registerTriggerUpperBoundCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, AnalogTriggerDataJNI::cancelTriggerUpperBoundCallback);
}
/**
* Get the upper bound.
*
* @return the upper bound
*/
public double getTriggerUpperBound() {
return AnalogTriggerDataJNI.getTriggerUpperBound(m_index);
}
/**
* Change the upper bound.
*
* @param triggerUpperBound the new upper bound
*/
public void setTriggerUpperBound(double triggerUpperBound) {
AnalogTriggerDataJNI.setTriggerUpperBound(m_index, triggerUpperBound);
}
/** Reset all simulation data for this object. */
public void resetData() {
AnalogTriggerDataJNI.resetData(m_index);
}
}