[hal] Add support for DMA to Java (#3158)

This commit is contained in:
Thad House
2021-06-14 19:56:42 -07:00
committed by GitHub
parent 85144e47ff
commit 4a36f86c81
39 changed files with 2013 additions and 97 deletions

View File

@@ -50,7 +50,7 @@ public class Counter implements CounterBase, Sendable, AutoCloseable {
protected DigitalSource m_downSource; // /< What makes the counter count down.
private boolean m_allocatedUpSource;
private boolean m_allocatedDownSource;
private int m_counter; // /< The FPGA counter object.
int m_counter; // /< The FPGA counter object.
private int m_index; // /< The index of this counter.
private double m_distancePerPulse; // distance of travel for each tick

View File

@@ -0,0 +1,110 @@
// 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.DMAJNI;
import edu.wpi.first.wpilibj.motorcontrol.PWMMotorController;
public class DMA implements AutoCloseable {
final int m_dmaHandle;
public DMA() {
m_dmaHandle = DMAJNI.initialize();
}
@Override
public void close() {
DMAJNI.free(m_dmaHandle);
}
public void setPause(boolean pause) {
DMAJNI.setPause(m_dmaHandle, pause);
}
public void setTimedTrigger(double periodSeconds) {
DMAJNI.setTimedTrigger(m_dmaHandle, periodSeconds);
}
public void setTimedTriggerCycles(int cycles) {
DMAJNI.setTimedTriggerCycles(m_dmaHandle, cycles);
}
public void addEncoder(Encoder encoder) {
DMAJNI.addEncoder(m_dmaHandle, encoder.m_encoder);
}
public void addEncoderPeriod(Encoder encoder) {
DMAJNI.addEncoderPeriod(m_dmaHandle, encoder.m_encoder);
}
public void addCounter(Counter counter) {
DMAJNI.addCounter(m_dmaHandle, counter.m_counter);
}
public void addCounterPeriod(Counter counter) {
DMAJNI.addCounterPeriod(m_dmaHandle, counter.m_counter);
}
public void addDigitalSource(DigitalSource digitalSource) {
DMAJNI.addDigitalSource(m_dmaHandle, digitalSource.getPortHandleForRouting());
}
public void addDutyCycle(DutyCycle dutyCycle) {
DMAJNI.addDutyCycle(m_dmaHandle, dutyCycle.m_handle);
}
public void addAnalogInput(AnalogInput analogInput) {
DMAJNI.addAnalogInput(m_dmaHandle, analogInput.m_port);
}
public void addAveragedAnalogInput(AnalogInput analogInput) {
DMAJNI.addAveragedAnalogInput(m_dmaHandle, analogInput.m_port);
}
public void addAnalogAccumulator(AnalogInput analogInput) {
DMAJNI.addAnalogAccumulator(m_dmaHandle, analogInput.m_port);
}
/**
* Sets an external DMA trigger.
*
* @param source the source to trigger from.
* @param rising trigger on rising edge.
* @param falling trigger on falling edge.
* @return the index of the trigger
*/
public int setExternalTrigger(DigitalSource source, boolean rising, boolean falling) {
return DMAJNI.setExternalTrigger(
m_dmaHandle,
source.getPortHandleForRouting(),
source.getAnalogTriggerTypeForRouting(),
rising,
falling);
}
public int setPwmEdgeTrigger(PWMMotorController pwm, boolean rising, boolean falling) {
return DMAJNI.setExternalTrigger(m_dmaHandle, pwm.getPwmHandle(), 0, rising, falling);
}
public int setPwmEdgeTrigger(PWM pwm, boolean rising, boolean falling) {
return DMAJNI.setExternalTrigger(m_dmaHandle, pwm.getHandle(), 0, rising, falling);
}
public void clearSensors() {
DMAJNI.clearSensors(m_dmaHandle);
}
public void clearExternalTriggers() {
DMAJNI.clearExternalTriggers(m_dmaHandle);
}
public void start(int queueDepth) {
DMAJNI.startDMA(m_dmaHandle, queueDepth);
}
public void stop() {
DMAJNI.stopDMA(m_dmaHandle);
}
}

View File

@@ -0,0 +1,126 @@
// 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.DMAJNISample;
public class DMASample {
public enum DMAReadStatus {
kOk(1),
kTimeout(2),
kError(3);
private final int value;
DMAReadStatus(int value) {
this.value = value;
}
public int getValue() {
return value;
}
/**
* Constructs a DMAReadStatus from a raw value.
*
* @param value raw value
* @return enum value
*/
public static DMAReadStatus getValue(int value) {
if (value == 1) {
return kOk;
} else if (value == 2) {
return kTimeout;
}
return kError;
}
}
private final DMAJNISample m_dmaSample = new DMAJNISample();
public DMAReadStatus update(DMA dma, double timeoutSeconds) {
return DMAReadStatus.getValue(m_dmaSample.update(dma.m_dmaHandle, timeoutSeconds));
}
public int getCaptureSize() {
return m_dmaSample.getCaptureSize();
}
public int getTriggerChannels() {
return m_dmaSample.getTriggerChannels();
}
public int getRemaining() {
return m_dmaSample.getRemaining();
}
public long getTime() {
return m_dmaSample.getTime();
}
public double getTimeStamp() {
return getTime() * 1.0e-6;
}
public int getEncoderRaw(Encoder encoder) {
return m_dmaSample.getEncoder(encoder.m_encoder);
}
/**
* Gets the scaled encoder distance for this sample.
*
* @param encoder the encoder to use to read
* @return the distance
*/
public double getEncoderDistance(Encoder encoder) {
double val = getEncoderRaw(encoder);
val *= encoder.getDecodingScaleFactor();
val *= encoder.getDistancePerPulse();
return val;
}
public int getEncoderPeriodRaw(Encoder encoder) {
return m_dmaSample.getEncoderPeriod(encoder.m_encoder);
}
public int getCounter(Counter counter) {
return m_dmaSample.getCounter(counter.m_counter);
}
public int getCounterPeriod(Counter counter) {
return m_dmaSample.getCounterPeriod(counter.m_counter);
}
public boolean getDigitalSource(DigitalSource digitalSource) {
return m_dmaSample.getDigitalSource(digitalSource.getPortHandleForRouting());
}
public int getAnalogInputRaw(AnalogInput analogInput) {
return m_dmaSample.getAnalogInput(analogInput.m_port);
}
public double getAnalogInputVoltage(AnalogInput analogInput) {
return AnalogJNI.getAnalogValueToVolts(analogInput.m_port, getAnalogInputRaw(analogInput));
}
public int getAveragedAnalogInputRaw(AnalogInput analogInput) {
return m_dmaSample.getAnalogInputAveraged(analogInput.m_port);
}
public double getAveragedAnalogInputVoltage(AnalogInput analogInput) {
return AnalogJNI.getAnalogValueToVolts(
analogInput.m_port, getAveragedAnalogInputRaw(analogInput));
}
public int getDutyCycleOutputRaw(DutyCycle dutyCycle) {
return m_dmaSample.getDutyCycleOutput(dutyCycle.m_handle);
}
public double getDutyCycleOutput(DutyCycle dutyCycle) {
return m_dmaSample.getDutyCycleOutput(dutyCycle.m_handle)
/ (double) dutyCycle.getOutputScaleFactor();
}
}

View File

@@ -52,8 +52,9 @@ public class Encoder implements CounterBase, Sendable, AutoCloseable {
private boolean m_allocatedA;
private boolean m_allocatedB;
private boolean m_allocatedI;
private final EncodingType m_encodingType;
private int m_encoder; // the HAL encoder object
int m_encoder; // the HAL encoder object
/**
* Common initialization code for Encoders. This code allocates resources for Encoders and is
@@ -131,6 +132,7 @@ public class Encoder implements CounterBase, Sendable, AutoCloseable {
m_allocatedI = false;
m_aSource = new DigitalInput(channelA);
m_bSource = new DigitalInput(channelB);
m_encodingType = encodingType;
SendableRegistry.addChild(this, m_aSource);
SendableRegistry.addChild(this, m_bSource);
initEncoder(reverseDirection, encodingType);
@@ -230,6 +232,7 @@ public class Encoder implements CounterBase, Sendable, AutoCloseable {
m_allocatedA = false;
m_allocatedB = false;
m_allocatedI = false;
m_encodingType = encodingType;
m_aSource = sourceA;
m_bSource = sourceB;
initEncoder(reverseDirection, encodingType);
@@ -540,6 +543,24 @@ public class Encoder implements CounterBase, Sendable, AutoCloseable {
EncoderJNI.setEncoderSimDevice(m_encoder, device.getNativeHandle());
}
/**
* Gets the decoding scale factor for scaling raw values to full counts.
*
* @return decoding scale factor
*/
public double getDecodingScaleFactor() {
switch (m_encodingType) {
case k1X:
return 1.0;
case k2X:
return 0.5;
case k4X:
return 0.25;
default:
return 0.0;
}
}
@Override
public void initSendable(SendableBuilder builder) {
if (EncoderJNI.getEncoderEncodingType(m_encoder) == EncodingType.k4X.value) {

View File

@@ -37,8 +37,7 @@ public class PWM implements Sendable, AutoCloseable {
private final int m_channel;
// Package private to use from AddressableLED
int m_handle;
private int m_handle;
/**
* Allocate a PWM given a channel.
@@ -246,6 +245,15 @@ public class PWM implements Sendable, AutoCloseable {
PWMJNI.latchPWMZero(m_handle);
}
/**
* Get the underlying handle.
*
* @return Underlying PWM handle
*/
public int getHandle() {
return m_handle;
}
@Override
public void initSendable(SendableBuilder builder) {
builder.setSmartDashboardType("PWM");

View File

@@ -86,6 +86,15 @@ public abstract class PWMMotorController extends MotorSafety
return "PWM " + getChannel();
}
/**
* Gets the backing PWM handle.
*
* @return The pwm handle.
*/
public int getPwmHandle() {
return m_pwm.getHandle();
}
/**
* Gets the PWM channel number.
*