mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-24 01:31:46 +00:00
Removed AnalogModule, DigitalModule, and Module from Java
Change-Id: I42c58237f1e14d0ebae1c7266aecda00d51eeae1
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
|
||||
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
@@ -53,7 +53,7 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
* Construct an analog channel.
|
||||
*
|
||||
* @param channel
|
||||
* The channel number to represent.
|
||||
* The channel number to represent.
|
||||
*/
|
||||
public AnalogInput(final int channel) {
|
||||
m_channel = channel;
|
||||
@@ -69,7 +69,7 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
+ " is already allocated");
|
||||
}
|
||||
|
||||
ByteBuffer port_pointer = AnalogJNI.getPortWithModule((byte) 1, (byte) channel);
|
||||
ByteBuffer port_pointer = AnalogJNI.getPort((byte) channel);
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
@@ -91,21 +91,12 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the analog module.
|
||||
* Get a sample straight from this channel. The sample is a 12-bit value
|
||||
* representing the 0V to 10V range of the A/D converter. The units are in
|
||||
* A/D converter codes. Use GetVoltage() to get the analog value in
|
||||
* calibrated units.
|
||||
*
|
||||
* @return The AnalogModule.
|
||||
*/
|
||||
public AnalogModule getModule() {
|
||||
return AnalogModule.getInstance(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a sample straight from this channel on the module. The sample is a
|
||||
* 12-bit value representing the -10V to 10V range of the A/D converter in
|
||||
* the module. The units are in A/D converter codes. Use GetVoltage() to get
|
||||
* the analog value in calibrated units.
|
||||
*
|
||||
* @return A sample straight from this channel on the module.
|
||||
* @return A sample straight from this channel.
|
||||
*/
|
||||
public int getValue() {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
@@ -122,8 +113,8 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
* SetOversampleBits(). The value configured in setAverageBits() will cause
|
||||
* this value to be averaged 2**bits number of samples. This is not a
|
||||
* sliding window. The sample will not change until 2**(OversamplBits +
|
||||
* AverageBits) samples have been acquired from the module on this channel.
|
||||
* Use getAverageVoltage() to get the analog value in calibrated units.
|
||||
* AverageBits) samples have been acquired from this channel. Use
|
||||
* getAverageVoltage() to get the analog value in calibrated units.
|
||||
*
|
||||
* @return A sample from the oversample and average engine for this channel.
|
||||
*/
|
||||
@@ -137,11 +128,11 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a scaled sample straight from this channel on the module. The value
|
||||
* is scaled to units of Volts using the calibrated scaling data from
|
||||
* getLSBWeight() and getOffset().
|
||||
* Get a scaled sample straight from this channel. The value is scaled to
|
||||
* units of Volts using the calibrated scaling data from getLSBWeight() and
|
||||
* getOffset().
|
||||
*
|
||||
* @return A scaled sample straight from this channel on the module.
|
||||
* @return A scaled sample straight from this channel.
|
||||
*/
|
||||
public double getVoltage() {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
@@ -161,7 +152,7 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
* stable, but it will update more slowly.
|
||||
*
|
||||
* @return A scaled sample from the output of the oversample and average
|
||||
* engine for this channel.
|
||||
* engine for this channel.
|
||||
*/
|
||||
public double getAverageVoltage() {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
@@ -175,7 +166,7 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
/**
|
||||
* Get the factory scaling least significant bit weight constant. The least
|
||||
* significant bit weight constant for the channel that was calibrated in
|
||||
* manufacturing and stored in an eeprom in the module.
|
||||
* manufacturing and stored in an eeprom.
|
||||
*
|
||||
* Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
|
||||
*
|
||||
@@ -192,8 +183,7 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
|
||||
/**
|
||||
* Get the factory scaling offset constant. The offset constant for the
|
||||
* channel that was calibrated in manufacturing and stored in an eeprom in
|
||||
* the module.
|
||||
* channel that was calibrated in manufacturing and stored in an eeprom.
|
||||
*
|
||||
* Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
|
||||
*
|
||||
@@ -223,7 +213,7 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
* automatically in the FPGA.
|
||||
*
|
||||
* @param bits
|
||||
* The number of averaging bits.
|
||||
* The number of averaging bits.
|
||||
*/
|
||||
public void setAverageBits(final int bits) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
@@ -255,7 +245,7 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
* oversampling is done automatically in the FPGA.
|
||||
*
|
||||
* @param bits
|
||||
* The number of oversample bits.
|
||||
* The number of oversample bits.
|
||||
*/
|
||||
public void setOversampleBits(final int bits) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
@@ -306,7 +296,7 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
* This will be added to all values returned to the user.
|
||||
*
|
||||
* @param initialValue
|
||||
* The value that the accumulator should start from when reset.
|
||||
* The value that the accumulator should start from when reset.
|
||||
*/
|
||||
public void setAccumulatorInitialValue(long initialValue) {
|
||||
m_accumulatorOffset = initialValue;
|
||||
@@ -396,7 +386,7 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
* can be used for averaging.
|
||||
*
|
||||
* @param result
|
||||
* AccumulatorResult object to store the results in.
|
||||
* AccumulatorResult object to store the results in.
|
||||
*/
|
||||
public void getAccumulatorOutput(AccumulatorResult result) {
|
||||
if (result == null) {
|
||||
@@ -435,16 +425,41 @@ public class AnalogInput extends SensorBase implements PIDSource,
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setSampleRate(final double samplesPerSecond) {
|
||||
// TODO: This will change when variable size scan lists are implemented.
|
||||
// TODO: Need float comparison with epsilon.
|
||||
/**
|
||||
* Set the sample rate.
|
||||
*
|
||||
* This is a global setting for all channels.
|
||||
*
|
||||
* @param samplesPerSecond The number of samples per second.
|
||||
*/
|
||||
public static void setGlobalSampleRate(final double samplesPerSecond) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
AnalogJNI.setAnalogSampleRate((float) samplesPerSecond, status.asIntBuffer());
|
||||
|
||||
AnalogJNI.setAnalogSampleRate((float)samplesPerSecond, status.asIntBuffer());
|
||||
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current sample rate.
|
||||
*
|
||||
* This assumes one entry in the scan list. This is a global setting for
|
||||
* all channels.
|
||||
*
|
||||
* @return Sample rate.
|
||||
*/
|
||||
public static double getGlobalSampleRate() {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
double value = AnalogJNI.getAnalogSampleRate(status.asIntBuffer());
|
||||
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the average value for use with PIDController
|
||||
*
|
||||
|
||||
@@ -1,316 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tModuleType;
|
||||
import edu.wpi.first.wpilibj.hal.AnalogJNI;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
|
||||
/**
|
||||
* Analog Module class.
|
||||
* Each module can independently sample its channels at a configurable rate.
|
||||
* There is a 64-bit hardware accumulator associated with channel 1 on each module.
|
||||
* The accumulator is attached to the output of the oversample and average engine so that the center
|
||||
* value can be specified in higher resolution resulting in less error.
|
||||
*/
|
||||
public class AnalogModule extends Module {
|
||||
|
||||
/**
|
||||
* The time base used by the module
|
||||
*/
|
||||
public static final int kTimebase = 40000000;
|
||||
/**
|
||||
* The default number of Oversample bits to use
|
||||
*/
|
||||
public static final int kDefaultOversampleBits = 0;
|
||||
/**
|
||||
* The default number of averaging bits to use
|
||||
*/
|
||||
public static final int kDefaultAverageBits = 7;
|
||||
/**
|
||||
* The default sample rate
|
||||
*/
|
||||
public static final double kDefaultSampleRate = 50000.0;
|
||||
private ByteBuffer[] m_ports;
|
||||
|
||||
/**
|
||||
* Get an instance of an Analog Module.
|
||||
*
|
||||
* Singleton analog module creation where a module is allocated on the first use
|
||||
* and the same module is returned on subsequent uses.
|
||||
*
|
||||
* @param moduleNumber The index of the analog module to get (1 or 2).
|
||||
* @return The AnalogModule.
|
||||
*/
|
||||
public static synchronized AnalogModule getInstance(final int moduleNumber) {
|
||||
checkAnalogModule(moduleNumber);
|
||||
return (AnalogModule) getModule(tModuleType.kModuleType_Analog, moduleNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of an analog module.
|
||||
*
|
||||
* Create an instance of the analog module object. Initialize all the parameters
|
||||
* to reasonable values on start.
|
||||
* Setting a global value on an analog module can be done only once unless subsequent
|
||||
* values are set the previously set value.
|
||||
* Analog modules are a singleton, so the constructor is never called outside of this class.
|
||||
*
|
||||
* @param moduleNumber The index of the analog module to create (1 or 2).
|
||||
*/
|
||||
protected AnalogModule(final int moduleNumber) {
|
||||
super(tModuleType.kModuleType_Analog, moduleNumber);
|
||||
|
||||
m_ports = new ByteBuffer[8];
|
||||
for (int i = 0; i < SensorBase.kAnalogInputChannels; i++) {
|
||||
ByteBuffer port_pointer = AnalogJNI.getPortWithModule((byte) moduleNumber, (byte) i);
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
// XXX: Uncomment when analogchannel has been fixed
|
||||
// m_ports[i] = HALLibrary.initializeAnalogPort(port_pointer, status);
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sample rate on the module.
|
||||
*
|
||||
* This is a global setting for the module and effects all channels.
|
||||
*
|
||||
* @param samplesPerSecond
|
||||
* The number of samples per channel per second.
|
||||
*/
|
||||
public void setSampleRate(final double samplesPerSecond) {
|
||||
// TODO: This will change when variable size scan lists are implemented.
|
||||
// TODO: Need float comparison with epsilon.
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
AnalogJNI.setAnalogSampleRateWithModule((byte) m_moduleNumber, (float) samplesPerSecond, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current sample rate on the module.
|
||||
*
|
||||
* This assumes one entry in the scan list. This is a global setting for the
|
||||
* module and effects all channels.
|
||||
*
|
||||
* @return Sample rate.
|
||||
*/
|
||||
public double getSampleRate() {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
double value = AnalogJNI.getAnalogSampleRateWithModule((byte) m_moduleNumber, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of averaging bits.
|
||||
*
|
||||
* This sets the number of averaging bits. The actual number of averaged
|
||||
* samples is 2**bits. The averaging is done automatically in the FPGA.
|
||||
*
|
||||
* @param channel
|
||||
* Analog channel to configure.
|
||||
* @param bits
|
||||
* Number of bits to average.
|
||||
*/
|
||||
public void setAverageBits(final int channel, final int bits) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
AnalogJNI.setAnalogAverageBits(m_ports[channel], bits, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of averaging bits.
|
||||
*
|
||||
* This gets the number of averaging bits from the FPGA. The actual number
|
||||
* of averaged samples is 2**bits. The averaging is done automatically in
|
||||
* the FPGA.
|
||||
*
|
||||
* @param channel Channel to address.
|
||||
* @return Bits to average.
|
||||
*/
|
||||
public int getAverageBits(final int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int value = AnalogJNI.getAnalogAverageBits(m_ports[channel], status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of oversample bits.
|
||||
*
|
||||
* This sets the number of oversample bits. The actual number of oversampled values is 2**bits.
|
||||
* Use oversampling to improve the resolution of your measurements at the expense of sampling rate.
|
||||
* The oversampling is done automatically in the FPGA.
|
||||
*
|
||||
* @param channel Analog channel to configure.
|
||||
* @param bits Number of bits to oversample.
|
||||
*/
|
||||
public void setOversampleBits(final int channel, final int bits) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
AnalogJNI.setAnalogOversampleBits(m_ports[channel], bits, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of oversample bits.
|
||||
*
|
||||
* This gets the number of oversample bits from the FPGA. The actual number
|
||||
* of oversampled values is 2**bits. The oversampling is done automatically
|
||||
* in the FPGA.
|
||||
*
|
||||
* @param channel Channel to address.
|
||||
* @return Bits to oversample.
|
||||
*/
|
||||
public int getOversampleBits(final int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int value = AnalogJNI.getAnalogOversampleBits(m_ports[channel], status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw analog value.
|
||||
*
|
||||
* Get the analog value as it is returned from the D/A converter.
|
||||
*
|
||||
* @param channel Channel number to read.
|
||||
* @return Raw value.
|
||||
*/
|
||||
public int getValue(final int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int value = AnalogJNI.getAnalogValue(m_ports[channel], status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw averaged and oversampled value.
|
||||
*
|
||||
* @param channel Channel number to read.
|
||||
* @return The averaged and oversampled raw value.
|
||||
*/
|
||||
public int getAverageValue(final int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int value = AnalogJNI.getAnalogAverageValue(m_ports[channel], status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a voltage to a raw value for a specified channel.
|
||||
*
|
||||
* This process depends on the calibration of each channel, so the channel
|
||||
* must be specified.
|
||||
*
|
||||
* @todo This assumes raw values. Oversampling not supported as is.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to convert for.
|
||||
* @param voltage
|
||||
* The voltage to convert.
|
||||
* @return The raw value for the channel.
|
||||
*/
|
||||
public int voltsToValue(final int channel, final double voltage) {
|
||||
// wpi_assert(voltage >= -10.0 && voltage <= 10.0);
|
||||
ByteBuffer status = ByteBuffer.allocate(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int value = AnalogJNI.getAnalogVoltsToValue(m_ports[channel], (float) voltage, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the voltage.
|
||||
*
|
||||
* Return the voltage from the A/D converter.
|
||||
*
|
||||
* @param channel The channel to read.
|
||||
* @return The scaled voltage from the channel.
|
||||
*/
|
||||
public double getVoltage(final int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
double value = AnalogJNI.getAnalogVoltage(m_ports[channel], status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the averaged voltage.
|
||||
*
|
||||
* Return the averaged voltage from the A/D converter.
|
||||
*
|
||||
* @param channel The channel to read.
|
||||
* @return The scaled averaged and oversampled voltage from the channel.
|
||||
*/
|
||||
public double getAverageVoltage(final int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
double value = AnalogJNI.getAnalogAverageVoltage(m_ports[channel], status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the LSB Weight portion of the calibration for a channel.
|
||||
*
|
||||
* @param channel The channel to get calibration data for.
|
||||
* @return LSB Weight calibration point.
|
||||
*/
|
||||
public long getLSBWeight(final int channel) {
|
||||
// TODO: add scaling to make this worth while.
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
long value = AnalogJNI.getAnalogLSBWeight(m_ports[channel], status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Offset portion of the calibration for a channel.
|
||||
*
|
||||
* @param channel The channel to get calibration data for.
|
||||
* @return Offset calibration point.
|
||||
*/
|
||||
public int getOffset(final int channel) {
|
||||
// TODO: add scaling to make this worth while.
|
||||
// TODO: actually use this function.
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int value = AnalogJNI.getAnalogOffset(m_ports[channel], status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Copyright (c) FIRST 2014. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
@@ -28,113 +28,113 @@ import edu.wpi.first.wpilibj.util.CheckedAllocationException;
|
||||
* Analog output class.
|
||||
*/
|
||||
public class AnalogOutput extends SensorBase implements LiveWindowSendable {
|
||||
private static Resource channels = new Resource(kAnalogOutputChannels);
|
||||
private ByteBuffer m_port;
|
||||
private int m_channel;
|
||||
private static Resource channels = new Resource(kAnalogOutputChannels);
|
||||
private ByteBuffer m_port;
|
||||
private int m_channel;
|
||||
|
||||
/**
|
||||
* Construct an analog output on a specified MXP channel.
|
||||
*
|
||||
* @param channel
|
||||
* The channel number to represent.
|
||||
*/
|
||||
public AnalogOutput(final int channel) {
|
||||
m_channel = channel;
|
||||
/**
|
||||
* Construct an analog output on a specified MXP channel.
|
||||
*
|
||||
* @param channel
|
||||
* The channel number to represent.
|
||||
*/
|
||||
public AnalogOutput(final int channel) {
|
||||
m_channel = channel;
|
||||
|
||||
if (AnalogJNI.checkAnalogOutputChannel(channel) == 0) {
|
||||
throw new AllocationException("Analog output channel " + m_channel
|
||||
+ " cannot be allocated. Channel is not present.");
|
||||
}
|
||||
try {
|
||||
channels.allocate(channel);
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException("Analog output channel " + m_channel
|
||||
+ " is already allocated");
|
||||
}
|
||||
if (AnalogJNI.checkAnalogOutputChannel(channel) == 0) {
|
||||
throw new AllocationException("Analog output channel " + m_channel
|
||||
+ " cannot be allocated. Channel is not present.");
|
||||
}
|
||||
try {
|
||||
channels.allocate(channel);
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException("Analog output channel " + m_channel
|
||||
+ " is already allocated");
|
||||
}
|
||||
|
||||
ByteBuffer port_pointer = AnalogJNI.getPortWithModule((byte) 1, (byte) channel);
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
m_port = AnalogJNI.initializeAnalogOutputPort(port_pointer, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
ByteBuffer port_pointer = AnalogJNI.getPort((byte)channel);
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
m_port = AnalogJNI.initializeAnalogOutputPort(port_pointer, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
|
||||
LiveWindow.addSensor("AnalogOutput", channel, this);
|
||||
UsageReporting.report(tResourceType.kResourceType_AnalogChannel, channel, 1);
|
||||
}
|
||||
LiveWindow.addSensor("AnalogOutput", channel, this);
|
||||
UsageReporting.report(tResourceType.kResourceType_AnalogChannel, channel, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel destructor.
|
||||
*/
|
||||
public void free() {
|
||||
channels.free(m_channel);
|
||||
m_channel = 0;
|
||||
}
|
||||
/**
|
||||
* Channel destructor.
|
||||
*/
|
||||
public void free() {
|
||||
channels.free(m_channel);
|
||||
m_channel = 0;
|
||||
}
|
||||
|
||||
public void setVoltage(double voltage) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
public void setVoltage(double voltage) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
AnalogJNI.setAnalogOutput(m_port, voltage, status.asIntBuffer());
|
||||
AnalogJNI.setAnalogOutput(m_port, voltage, status.asIntBuffer());
|
||||
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
public double getVoltage() {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
public double getVoltage() {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
double voltage = AnalogJNI.getAnalogOutput(m_port, status.asIntBuffer());
|
||||
double voltage = AnalogJNI.getAnalogOutput(m_port, status.asIntBuffer());
|
||||
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
|
||||
return voltage;
|
||||
}
|
||||
return voltage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Analog Output";
|
||||
}
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Analog Output";
|
||||
}
|
||||
|
||||
private ITable m_table;
|
||||
private ITable m_table;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Value", getVoltage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Value", getVoltage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when entering the
|
||||
* LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when entering the
|
||||
* LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when exiting the
|
||||
* LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
}
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when exiting the
|
||||
* LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class AnalogTrigger implements IInputOutput {
|
||||
* the port to use for the analog trigger
|
||||
*/
|
||||
protected void initTrigger(final int channel) {
|
||||
ByteBuffer port_pointer = AnalogJNI.getPortWithModule((byte) 1, (byte) channel);
|
||||
ByteBuffer port_pointer = AnalogJNI.getPort((byte) channel);
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
IntBuffer index = IntBuffer.allocate(1);
|
||||
// XXX: Uncomment when analog has been fixed
|
||||
|
||||
@@ -1,542 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
//import com.sun.jna.Pointer;
|
||||
//import com.sun.jna.ptr.IntByReference;
|
||||
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tModuleType;
|
||||
import edu.wpi.first.wpilibj.hal.DIOJNI;
|
||||
import edu.wpi.first.wpilibj.hal.PWMJNI;
|
||||
import edu.wpi.first.wpilibj.hal.RelayJNI;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
|
||||
/**
|
||||
* Class representing a digital module
|
||||
*
|
||||
* @author dtjones
|
||||
*/
|
||||
public class DigitalModule extends Module {
|
||||
|
||||
/**
|
||||
* Expected loop timing
|
||||
*/
|
||||
public static final int kExpectedLoopTiming = 260;
|
||||
private int m_module;
|
||||
private ByteBuffer[] m_digital_ports;
|
||||
private ByteBuffer[] m_relay_ports;
|
||||
private ByteBuffer[] m_pwm_ports;
|
||||
|
||||
/**
|
||||
* Get an instance of an Digital Module. Singleton digital module creation
|
||||
* where a module is allocated on the first use and the same module is
|
||||
* returned on subsequent uses.
|
||||
*
|
||||
* @param moduleNumber
|
||||
* The number of the digital module to access.
|
||||
* @return The digital module of the specified number.
|
||||
*/
|
||||
public static synchronized DigitalModule getInstance(final int moduleNumber) {
|
||||
SensorBase.checkDigitalModule(moduleNumber);
|
||||
return (DigitalModule) getModule(tModuleType.kModuleType_Digital,
|
||||
moduleNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new digital module
|
||||
*
|
||||
* @param moduleNumber
|
||||
* The number of the digital module to use (1 or 2)
|
||||
*/
|
||||
protected DigitalModule(final int moduleNumber) {
|
||||
super(tModuleType.kModuleType_Digital, moduleNumber);
|
||||
m_module = moduleNumber;
|
||||
|
||||
m_digital_ports = new ByteBuffer[SensorBase.kDigitalChannels];
|
||||
for (int i = 0; i < SensorBase.kDigitalChannels; i++) {
|
||||
ByteBuffer port_pointer = DIOJNI.getPortWithModule(
|
||||
(byte) moduleNumber, (byte) i);
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
m_digital_ports[i] = DIOJNI.initializeDigitalPort(port_pointer,
|
||||
status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
m_relay_ports = new ByteBuffer[SensorBase.kRelayChannels];
|
||||
for (int i = 0; i < SensorBase.kRelayChannels; i++) {
|
||||
ByteBuffer port_pointer = RelayJNI.getPortWithModule(
|
||||
(byte) moduleNumber, (byte) i);
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
m_relay_ports[i] = RelayJNI.initializeDigitalPort(port_pointer,
|
||||
status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
m_pwm_ports = new ByteBuffer[SensorBase.kPwmChannels];
|
||||
for (int i = 0; i < SensorBase.kPwmChannels; i++) {
|
||||
ByteBuffer port_pointer = PWMJNI.getPortWithModule(
|
||||
(byte) moduleNumber, (byte) i);
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
m_pwm_ports[i] = PWMJNI.initializeDigitalPort(port_pointer,
|
||||
status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a PWM channel to the desired value. The values range from 0 to 255
|
||||
* and the period is controlled by the PWM Period and MinHigh registers.
|
||||
*
|
||||
* @param channel
|
||||
* The PWM channel to set.
|
||||
* @param value
|
||||
* The PWM value to set.
|
||||
*/
|
||||
public void setPWM(final int channel, final int value) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
PWMJNI.setPWM(m_pwm_ports[channel], (short) value, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from a PWM channel. The values range from 0 to 255.
|
||||
*
|
||||
* @param channel
|
||||
* The PWM channel to read from.
|
||||
* @return The raw PWM value.
|
||||
*/
|
||||
public int getPWM(final int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int value = (int) PWMJNI.getPWM(m_pwm_ports[channel], status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set how how often the PWM signal is squelched, thus scaling the period.
|
||||
*
|
||||
* @param channel
|
||||
* The PWM channel to configure.
|
||||
* @param squelchMask
|
||||
* The 2-bit mask of outputs to squelch.
|
||||
*/
|
||||
public void setPWMPeriodScale(final int channel, final int squelchMask) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
PWMJNI.setPWMPeriodScale(m_pwm_ports[channel], squelchMask,
|
||||
status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state of a relay. Set the state of a relay output to be forward.
|
||||
* Relays have two outputs and each is independently set to 0v or 12v.
|
||||
*
|
||||
* @param channel
|
||||
* The Relay channel.
|
||||
* @param on
|
||||
* Indicates whether to set the relay to the On state.
|
||||
*/
|
||||
public void setRelayForward(final int channel, final boolean on) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
RelayJNI.setRelayForward(m_relay_ports[channel], (byte) (on ? 1
|
||||
: 0), status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state of a relay. Set the state of a relay output to be reverse.
|
||||
* Relays have two outputs and each is independently set to 0v or 12v.
|
||||
*
|
||||
* @param channel
|
||||
* The Relay channel.
|
||||
* @param on
|
||||
* Indicates whether to set the relay to the On state.
|
||||
*/
|
||||
public void setRelayReverse(final int channel, final boolean on) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
RelayJNI.setRelayReverse(m_relay_ports[channel], (byte) (on ? 1
|
||||
: 0), status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current state of the forward relay channel
|
||||
*
|
||||
* @param channel
|
||||
* the channel of the relay to get
|
||||
* @return The current state of the relay.
|
||||
*/
|
||||
public boolean getRelayForward(int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
boolean value = RelayJNI.getRelayForward(m_relay_ports[channel],
|
||||
status.asIntBuffer()) != 0;
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current state of all of the forward relay channels on this
|
||||
* module.
|
||||
*
|
||||
* @return The state of all forward relay channels as a byte.
|
||||
*/
|
||||
public byte getRelayForward() {
|
||||
byte value = 0;
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
for (int i = 0; i < SensorBase.kRelayChannels; i++) {
|
||||
value |= RelayJNI.getRelayForward(m_relay_ports[i], status.asIntBuffer()) << i;
|
||||
}
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current state of the reverse relay channel
|
||||
*
|
||||
* @param channel
|
||||
* the channel of the relay to get
|
||||
* @return The current statte of the relay
|
||||
*/
|
||||
public boolean getRelayReverse(int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
boolean value = RelayJNI.getRelayReverse(m_relay_ports[channel],
|
||||
status.asIntBuffer()) != 0;
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current state of all of the reverse relay channels on this
|
||||
* module.
|
||||
*
|
||||
* @return The state of all forward relay channels as a byte.
|
||||
*/
|
||||
public byte getRelayReverse() {
|
||||
byte value = 0;
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
for (int i = 0; i < SensorBase.kRelayChannels; i++) {
|
||||
value |= RelayJNI.getRelayReverse(m_relay_ports[i], status.asIntBuffer()) << i;
|
||||
}
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate Digital I/O channels. Allocate channels so that they are not
|
||||
* accidently reused. Also the direction is set at the time of the
|
||||
* allocation.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to allocate.
|
||||
* @param input
|
||||
* Indicates whether the I/O pin is an input (true) or an output
|
||||
* (false).
|
||||
* @return True if the I/O pin was allocated, false otherwise.
|
||||
*/
|
||||
public boolean allocateDIO(final int channel, final boolean input) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
boolean allocated = DIOJNI.allocateDIO(
|
||||
m_digital_ports[channel], (byte) (input ? 1 : 0), status.asIntBuffer()) != 0;
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return allocated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resource associated with a digital I/O channel.
|
||||
*
|
||||
* @param channel
|
||||
* The channel whose resources should be freed.
|
||||
*/
|
||||
public void freeDIO(final int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
DIOJNI.freeDIO(m_digital_ports[channel], status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a digital I/O bit to the FPGA. Set a single value on a digital I/O
|
||||
* channel.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to set.
|
||||
* @param value
|
||||
* The value to set.
|
||||
*/
|
||||
public void setDIO(final int channel, final boolean value) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
DIOJNI.setDIO(m_digital_ports[channel], (byte) (value ? 1 : 0),
|
||||
status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a digital I/O bit from the FPGA. Get a single value from a digital
|
||||
* I/O channel.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to read
|
||||
* @return The value of the selected channel
|
||||
*/
|
||||
public boolean getDIO(final int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
boolean value = DIOJNI.getDIO(m_digital_ports[channel], status.asIntBuffer()) != 0;
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the state of all the Digital I/O lines from the FPGA These are not
|
||||
* remapped to logical order. They are still in hardware order.
|
||||
*
|
||||
* @return The state of all the Digital IO lines in hardware order
|
||||
*/
|
||||
public short getAllDIO() {
|
||||
short value = 0;
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
for (int i = 0; i < SensorBase.kDigitalChannels; i++) {
|
||||
value |= DIOJNI.getDIO(m_digital_ports[i], status.asIntBuffer()) << i;
|
||||
}
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the direction of a digital I/O line
|
||||
*
|
||||
* @param channel
|
||||
* The channel of the DIO to get the direction of.
|
||||
* @return True if the digital channel is configured as an output, false if
|
||||
* it is an input
|
||||
*/
|
||||
public boolean getDIODirection(int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
boolean value = DIOJNI.getDIODirection(
|
||||
m_digital_ports[channel], status.asIntBuffer()) != 0;
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the direction of all the Digital I/O lines from the FPGA A 1 bit
|
||||
* means output and a 0 bit means input. These are not remapped to logical
|
||||
* order. They are still in hardware order.
|
||||
*
|
||||
* @return The direction of all the Digital IO lines in hardware order
|
||||
*/
|
||||
public short getDIODirection() {
|
||||
byte value = 0;
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
for (int i = 0; i < SensorBase.kDigitalChannels; i++) {
|
||||
value |= DIOJNI.getDIODirection(m_digital_ports[i], status.asIntBuffer()) << i;
|
||||
}
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a single pulse. Write a pulse to the specified digital output
|
||||
* channel. There can only be a single pulse going at any time.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to pulse.
|
||||
* @param pulseLength
|
||||
* The length of the pulse.
|
||||
*/
|
||||
public void pulse(final int channel, final float pulseLength) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
DIOJNI.pulse(m_digital_ports[channel], pulseLength, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Generate a single pulse. Write a pulse to the specified
|
||||
* digital output channel. There can only be a single pulse
|
||||
* going at any time.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to pulse.
|
||||
* @param pulseLength
|
||||
* The length of the pulse.
|
||||
*/
|
||||
public void pulse(final int channel, final int pulseLength) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
float convertedPulse = (float) (pulseLength / 1.0e9 * (DIOJNI.getLoopTiming(status.asIntBuffer()) * 25));
|
||||
System.err
|
||||
.println("You should use the float version of pulse for portability. This is deprecated");
|
||||
DIOJNI.pulse(m_digital_ports[channel], convertedPulse, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a DIO line to see if it is currently generating a pulse.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to check.
|
||||
* @return True if the channel is pulsing, false otherwise.
|
||||
*/
|
||||
public boolean isPulsing(final int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
boolean value = DIOJNI.isPulsing(m_digital_ports[channel],
|
||||
status.asIntBuffer()) != 0;
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if any DIO line is currently generating a pulse.
|
||||
*
|
||||
* @return True if any channel is pulsing, false otherwise.
|
||||
*/
|
||||
public boolean isPulsing() {
|
||||
boolean value;
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
value = DIOJNI.isAnyPulsingWithModule((byte) m_module, status.asIntBuffer()) != 0;
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a DO PWM Generator. Allocate PWM generators so that they are not
|
||||
* accidently reused.
|
||||
*/
|
||||
public ByteBuffer allocateDO_PWM() {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
ByteBuffer value = PWMJNI.allocatePWMWithModule((byte) m_module, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resource associated with a DO PWM generator.
|
||||
*/
|
||||
public void freeDO_PWM(ByteBuffer pwmGenerator) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
PWMJNI.freePWMWithModule((byte) m_module, pwmGenerator, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the frequency of the DO PWM generator.
|
||||
*
|
||||
* The valid range is from 0.6 Hz to 19 kHz. The frequency resolution is
|
||||
* logarithmic.
|
||||
*
|
||||
* @param rate
|
||||
* The frequency to output all digital output PWM signals on this
|
||||
* module.
|
||||
*/
|
||||
public void setDO_PWMRate(double rate) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
PWMJNI.setPWMRateWithModule((byte) m_module, rate, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure which DO channel the PWM siganl is output on
|
||||
*
|
||||
* @param pwmGenerator
|
||||
* The generator index reserved by allocateDO_PWM()
|
||||
* @param channel
|
||||
* The Digital Output channel to output on
|
||||
*/
|
||||
public void setDO_PWMOutputChannel(ByteBuffer pwmGenerator, int channel) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
PWMJNI.setPWMOutputChannelWithModule((byte) m_module, pwmGenerator,
|
||||
channel, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the duty-cycle of the PWM generator
|
||||
*
|
||||
* @param pwmGenerator
|
||||
* The generator index reserved by allocateDO_PWM()
|
||||
* @param dutyCycle
|
||||
* The percent duty cycle to output [0..1].
|
||||
*/
|
||||
public void setDO_PWMDutyCycle(ByteBuffer pwmGenerator, double dutyCycle) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
PWMJNI.setPWMDutyCycleWithModule((byte) m_module, pwmGenerator, dutyCycle, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the loop timing of the Digital Module
|
||||
*
|
||||
* @return The number of clock ticks per DIO loop
|
||||
*/
|
||||
public int getLoopTiming() {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int value = DIOJNI.getLoopTiming(status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -138,25 +138,22 @@ public class DigitalOutput extends DigitalSource implements IInputOutput,
|
||||
* The valid range is from 0.6 Hz to 19 kHz. The frequency resolution is
|
||||
* logarithmic.
|
||||
*
|
||||
* There is only one PWM frequency per digital module.
|
||||
* There is only one PWM frequency for all channnels.
|
||||
*
|
||||
* @param rate
|
||||
* The frequency to output all digital output PWM signals on this
|
||||
* module.
|
||||
* @param rate The frequency to output all digital output PWM signals.
|
||||
*/
|
||||
public void setPWMRate(double rate) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
PWMJNI.setPWMRateWithModule((byte) 1, rate,
|
||||
status.asIntBuffer());
|
||||
PWMJNI.setPWMRate(rate, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable a PWM Output on this line.
|
||||
*
|
||||
* Allocate one of the 4 DO PWM generator resources from this module.
|
||||
* Allocate one of the 4 DO PWM generator resources.
|
||||
*
|
||||
* Supply the initial duty-cycle to output so as to avoid a glitch when
|
||||
* first starting.
|
||||
@@ -173,12 +170,12 @@ public class DigitalOutput extends DigitalSource implements IInputOutput,
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
m_pwmGenerator = PWMJNI.allocatePWMWithModule((byte) 1, status.asIntBuffer());
|
||||
m_pwmGenerator = PWMJNI.allocatePWM(status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
PWMJNI.setPWMDutyCycle(m_pwmGenerator, initialDutyCycle,
|
||||
status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
PWMJNI.setPWMOutputChannelWithModule((byte) 1, m_pwmGenerator, m_channel, status.asIntBuffer());
|
||||
PWMJNI.setPWMOutputChannel(m_pwmGenerator, m_channel, status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,7 +190,7 @@ public class DigitalOutput extends DigitalSource implements IInputOutput,
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
PWMJNI.setPWMOutputChannel(m_pwmGenerator, kDigitalChannels, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
PWMJNI.freePWMWithModule((byte) 1, m_pwmGenerator, status.asIntBuffer());
|
||||
PWMJNI.freePWM(m_pwmGenerator, status.asIntBuffer());
|
||||
m_pwmGenerator = null;
|
||||
}
|
||||
|
||||
@@ -210,7 +207,7 @@ public class DigitalOutput extends DigitalSource implements IInputOutput,
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
PWMJNI.setPWMDutyCycleWithModule((byte) 1, m_pwmGenerator, dutyCycle, status.asIntBuffer());
|
||||
PWMJNI.setPWMDutyCycle(m_pwmGenerator, dutyCycle, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public abstract class DigitalSource extends InterruptableSensorBase {
|
||||
+ " is already allocated");
|
||||
}
|
||||
|
||||
ByteBuffer port_pointer = DIOJNI.getPortWithModule((byte) 1, (byte) channel);
|
||||
ByteBuffer port_pointer = DIOJNI.getPort((byte) channel);
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
@@ -52,9 +52,9 @@ public class GearTooth extends Counter implements ISensor {
|
||||
super(channel);
|
||||
enableDirectionSensing(directionSensitive);
|
||||
if(directionSensitive) {
|
||||
UsageReporting.report(tResourceType.kResourceType_GearTooth, channel, DigitalModule.getDefaultDigitalModule()-1, "D");
|
||||
UsageReporting.report(tResourceType.kResourceType_GearTooth, channel, 0, "D");
|
||||
} else {
|
||||
UsageReporting.report(tResourceType.kResourceType_GearTooth, channel, DigitalModule.getDefaultDigitalModule()-1);
|
||||
UsageReporting.report(tResourceType.kResourceType_GearTooth, channel, 0);
|
||||
}
|
||||
LiveWindow.addSensor("GearTooth", channel, this);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class Gyro extends SensorBase implements PIDSource, ISensor,
|
||||
m_analog.setOversampleBits(kOversampleBits);
|
||||
double sampleRate = kSamplesPerSecond
|
||||
* (1 << (kAverageBits + kOversampleBits));
|
||||
m_analog.setSampleRate(sampleRate);
|
||||
AnalogInput.setGlobalSampleRate(sampleRate);
|
||||
|
||||
Timer.delay(1.0);
|
||||
m_analog.initAccumulator();
|
||||
@@ -160,7 +160,7 @@ public class Gyro extends SensorBase implements PIDSource, ISensor,
|
||||
* 1e-9
|
||||
* m_analog.getLSBWeight()
|
||||
* (1 << m_analog.getAverageBits())
|
||||
/ (m_analog.getModule().getSampleRate() * m_voltsPerDegreePerSecond);
|
||||
/ (AnalogInput.getGlobalSampleRate() * m_voltsPerDegreePerSecond);
|
||||
|
||||
return scaledValue;
|
||||
}
|
||||
|
||||
@@ -28,11 +28,11 @@ import edu.wpi.first.wpilibj.util.BoundaryException;
|
||||
public class I2C extends SensorBase {
|
||||
public enum Port {kOnboard(0), kMXP(1);
|
||||
private int value;
|
||||
|
||||
|
||||
private Port(int value){
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
public int getValue(){
|
||||
return this.value;
|
||||
}
|
||||
@@ -44,21 +44,19 @@ public class I2C extends SensorBase {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param module
|
||||
* The Digital Module to which the device is connected.
|
||||
* @param deviceAddress
|
||||
* The address of the device on the I2C bus.
|
||||
*/
|
||||
public I2C(Port port, int deviceAddress) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
|
||||
m_port = port;
|
||||
m_deviceAddress = deviceAddress;
|
||||
|
||||
|
||||
I2CJNI.i2CInitialize((byte)m_port.getValue(), status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_I2C, deviceAddress);
|
||||
}
|
||||
|
||||
@@ -93,7 +91,7 @@ public class I2C extends SensorBase {
|
||||
ByteBuffer dataReceivedBuffer = ByteBuffer.allocateDirect(receiveSize);
|
||||
|
||||
aborted = I2CJNI
|
||||
.i2CTransaction((byte) m_port.getValue(), (byte) m_deviceAddress,
|
||||
.i2CTransaction((byte) m_port.getValue(), (byte) m_deviceAddress,
|
||||
dataToSendBuffer, (byte) sendSize,
|
||||
dataReceivedBuffer, (byte) receiveSize) != 0;
|
||||
/*if (status.get() == HALUtil.PARAMETER_OUT_OF_RANGE) {
|
||||
@@ -140,13 +138,13 @@ public class I2C extends SensorBase {
|
||||
byte[] buffer = new byte[2];
|
||||
buffer[0] = (byte) registerAddress;
|
||||
buffer[1] = (byte) data;
|
||||
|
||||
|
||||
ByteBuffer dataToSendBuffer = ByteBuffer.allocateDirect(2);
|
||||
dataToSendBuffer.put(buffer);
|
||||
|
||||
|
||||
return I2CJNI.i2CWrite((byte)m_port.getValue(), (byte) m_deviceAddress, dataToSendBuffer, (byte)buffer.length) < 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute a write transaction with the device.
|
||||
*
|
||||
@@ -156,10 +154,10 @@ public class I2C extends SensorBase {
|
||||
* @param data
|
||||
* The data to write to the device.
|
||||
*/
|
||||
public synchronized boolean writeBulk(byte[] data) {
|
||||
public synchronized boolean writeBulk(byte[] data) {
|
||||
ByteBuffer dataToSendBuffer = ByteBuffer.allocateDirect(data.length);
|
||||
dataToSendBuffer.put(data);
|
||||
|
||||
|
||||
return I2CJNI.i2CWrite((byte)m_port.getValue(), (byte) m_deviceAddress, dataToSendBuffer, (byte)data.length) < 0;
|
||||
}
|
||||
|
||||
@@ -190,7 +188,7 @@ public class I2C extends SensorBase {
|
||||
return transaction(registerAddressArray, registerAddressArray.length,
|
||||
buffer, count);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute a read only transaction with the device.
|
||||
*
|
||||
@@ -209,9 +207,9 @@ public class I2C extends SensorBase {
|
||||
if (buffer == null) {
|
||||
throw new NullPointerException("Null return buffer was given");
|
||||
}
|
||||
|
||||
|
||||
ByteBuffer dataReceivedBuffer = ByteBuffer.allocateDirect(count);
|
||||
|
||||
|
||||
int retVal = I2CJNI.i2CRead((byte)m_port.getValue(), (byte) m_deviceAddress, dataReceivedBuffer, (byte)count);
|
||||
dataReceivedBuffer.get(buffer);
|
||||
return retVal < 0;
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary;
|
||||
import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tModuleType;
|
||||
|
||||
/**
|
||||
* Base class for AnalogModule and DigitalModule.
|
||||
*
|
||||
* @author dtjones
|
||||
*/
|
||||
public class Module extends SensorBase {
|
||||
|
||||
/**
|
||||
* An array holding the object representing each module
|
||||
*/
|
||||
protected static Module[] m_modules = new Module[tModuleType.kModuleType_Solenoid * FRCNetworkCommunicationsLibrary.kMaxModuleNumber + (FRCNetworkCommunicationsLibrary.kMaxModuleNumber - 1)];
|
||||
/**
|
||||
* The module number of the module
|
||||
*/
|
||||
protected int m_moduleNumber;
|
||||
protected int m_moduleType;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param moduleNumber The number of this module (1 or 2).
|
||||
*/
|
||||
protected Module(int moduleType, final int moduleNumber) {
|
||||
m_modules[toIndex(moduleType, moduleNumber)] = this;
|
||||
m_moduleNumber = moduleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the module number associated with a module.
|
||||
*
|
||||
* @return The module's number.
|
||||
*/
|
||||
public int getModuleNumber() {
|
||||
return m_moduleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the module type associated with a module.
|
||||
*
|
||||
* @return The module's type.
|
||||
*/
|
||||
public int getModuleType() {
|
||||
return m_moduleType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static module singleton factory.
|
||||
*
|
||||
* @param moduleType The type of the module represented.
|
||||
* @param moduleNumber The module index within the module type.
|
||||
* @return the module
|
||||
*/
|
||||
public static Module getModule(int moduleType, int moduleNumber) {
|
||||
if(m_modules[toIndex(moduleType, moduleNumber)] == null) {
|
||||
if(moduleType == tModuleType.kModuleType_Analog) {
|
||||
new AnalogModule(moduleNumber);
|
||||
} else if (moduleType == tModuleType.kModuleType_Digital) {
|
||||
new DigitalModule(moduleNumber);
|
||||
/* } else if (moduleType.equals(ModulePresence.ModuleType.kSolenoid)) {
|
||||
new Sol
|
||||
*/
|
||||
} else {
|
||||
throw new RuntimeException("A module of type "+moduleType+" with module index "+moduleNumber);
|
||||
}
|
||||
}
|
||||
return m_modules[toIndex(moduleType, moduleNumber)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an index into m_modules based on type and number
|
||||
*
|
||||
* @param moduleType The type of the module represented.
|
||||
* @param moduleNumber The module index within the module type.
|
||||
* @return The index into m_modules.
|
||||
*/
|
||||
private static int toIndex(int moduleType, int moduleNumber) {
|
||||
if(moduleNumber == 0 || moduleNumber > FRCNetworkCommunicationsLibrary.kMaxModuleNumber)
|
||||
return 0;
|
||||
return moduleType * FRCNetworkCommunicationsLibrary.kMaxModuleNumber + (moduleNumber - 1);
|
||||
}
|
||||
}
|
||||
@@ -7,14 +7,19 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.PWMJNI;
|
||||
import edu.wpi.first.wpilibj.hal.DIOJNI;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
import edu.wpi.first.wpilibj.util.AllocationException;
|
||||
import edu.wpi.first.wpilibj.util.CheckedAllocationException;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
|
||||
/**
|
||||
* Class implements the PWM generation in the FPGA.
|
||||
@@ -32,427 +37,457 @@ import edu.wpi.first.wpilibj.util.CheckedAllocationException;
|
||||
* 0 = disabled (i.e. PWM output is held low)
|
||||
*/
|
||||
public class PWM extends SensorBase implements LiveWindowSendable {
|
||||
private static Resource allocated = new Resource( kPwmChannels);
|
||||
|
||||
/**
|
||||
* Represents the amount to multiply the minimum servo-pulse pwm period by.
|
||||
*/
|
||||
public static class PeriodMultiplier {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int k1X_val = 1;
|
||||
static final int k2X_val = 2;
|
||||
static final int k4X_val = 4;
|
||||
/**
|
||||
* Period Multiplier: don't skip pulses
|
||||
*/
|
||||
public static final PeriodMultiplier k1X = new PeriodMultiplier(k1X_val);
|
||||
/**
|
||||
* Period Multiplier: skip every other pulse
|
||||
*/
|
||||
public static final PeriodMultiplier k2X = new PeriodMultiplier(k2X_val);
|
||||
/**
|
||||
* Period Multiplier: skip three out of four pulses
|
||||
*/
|
||||
public static final PeriodMultiplier k4X = new PeriodMultiplier(k4X_val);
|
||||
|
||||
private PeriodMultiplier(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
private int m_channel;
|
||||
private ByteBuffer m_port;
|
||||
/**
|
||||
* kDefaultPwmPeriod is in ms
|
||||
*
|
||||
* - 20ms periods (50 Hz) are the "safest" setting in that this works for all devices
|
||||
* - 20ms periods seem to be desirable for Vex Motors
|
||||
* - 20ms periods are the specified period for HS-322HD servos, but work reliably down
|
||||
* to 10.0 ms; starting at about 8.5ms, the servo sometimes hums and get hot;
|
||||
* by 5.0ms the hum is nearly continuous
|
||||
* - 10ms periods work well for Victor 884
|
||||
* - 5ms periods allows higher update rates for Luminary Micro Jaguar speed controllers.
|
||||
* Due to the shipping firmware on the Jaguar, we can't run the update period less
|
||||
* than 5.05 ms.
|
||||
*
|
||||
* kDefaultPwmPeriod is the 1x period (5.05 ms). In hardware, the period scaling is implemented as an
|
||||
* output squelch to get longer periods for old devices.
|
||||
*/
|
||||
protected static final double kDefaultPwmPeriod = 5.05;
|
||||
/**
|
||||
* kDefaultPwmCenter is the PWM range center in ms
|
||||
*/
|
||||
protected static final double kDefaultPwmCenter = 1.5;
|
||||
/**
|
||||
* kDefaultPWMStepsDown is the number of PWM steps below the centerpoint
|
||||
*/
|
||||
protected static final int kDefaultPwmStepsDown = 1000;
|
||||
public static final int kPwmDisabled = 0;
|
||||
boolean m_eliminateDeadband;
|
||||
int m_maxPwm;
|
||||
int m_deadbandMaxPwm;
|
||||
int m_centerPwm;
|
||||
int m_deadbandMinPwm;
|
||||
int m_minPwm;
|
||||
|
||||
/**
|
||||
* Initialize PWMs given a channel.
|
||||
*
|
||||
* This method is private and is the common path for all the constructors
|
||||
* for creating PWM instances. Checks channel value ranges and allocates
|
||||
* the appropriate channel. The allocation is only done to help users
|
||||
* ensure that they don't double assign channels.
|
||||
*/
|
||||
private void initPWM(final int channel) {
|
||||
checkPWMChannel(channel);
|
||||
try {
|
||||
allocated.allocate(channel);
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException(
|
||||
"PWM channel " + channel + " is already allocated");
|
||||
}
|
||||
m_channel = channel;
|
||||
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
m_port = DIOJNI.initializeDigitalPort(DIOJNI.getPort((byte) m_channel), status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
|
||||
PWMJNI.setPWM(m_port, (short) 0, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
|
||||
m_eliminateDeadband = false;
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_PWM, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a PWM given a channel.
|
||||
*
|
||||
* @param channel The PWM channel.
|
||||
*/
|
||||
public PWM(final int channel) {
|
||||
initPWM(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the PWM channel.
|
||||
*
|
||||
* Free the resource associated with the PWM channel and set the value to 0.
|
||||
*/
|
||||
public void free() {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
PWMJNI.setPWM(m_port, (short) 0, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
|
||||
PWMJNI.freeDIO(m_port, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
|
||||
allocated.free(m_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally eliminate the deadband from a speed controller.
|
||||
* @param eliminateDeadband If true, set the motor curve on the Jaguar to eliminate
|
||||
* the deadband in the middle of the range. Otherwise, keep the full range without
|
||||
* modifying any values.
|
||||
*/
|
||||
public void enableDeadbandElimination(boolean eliminateDeadband) {
|
||||
m_eliminateDeadband = eliminateDeadband;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bounds on the PWM values.
|
||||
* This sets the bounds on the PWM values for a particular each type of controller. The values
|
||||
* determine the upper and lower speeds as well as the deadband bracket.
|
||||
* @deprecated Recommended to set bounds in ms using {@link #setBounds(double, double, double, double, double)}
|
||||
* @param max The Minimum pwm value
|
||||
* @param deadbandMax The high end of the deadband range
|
||||
* @param center The center speed (off)
|
||||
* @param deadbandMin The low end of the deadband range
|
||||
* @param min The minimum pwm value
|
||||
*/
|
||||
public void setBounds(final int max, final int deadbandMax, final int center, final int deadbandMin, final int min) {
|
||||
m_maxPwm = max;
|
||||
m_deadbandMaxPwm = deadbandMax;
|
||||
m_centerPwm = center;
|
||||
m_deadbandMinPwm = deadbandMin;
|
||||
m_minPwm = min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bounds on the PWM pulse widths.
|
||||
* This sets the bounds on the PWM values for a particular type of controller. The values
|
||||
* determine the upper and lower speeds as well as the deadband bracket.
|
||||
* @param max The max PWM pulse width in ms
|
||||
* @param deadbandMax The high end of the deadband range pulse width in ms
|
||||
* @param center The center (off) pulse width in ms
|
||||
* @param deadbandMin The low end of the deadband pulse width in ms
|
||||
* @param min The minimum pulse width in ms
|
||||
*/
|
||||
protected void setBounds(double max, double deadbandMax, double center, double deadbandMin, double min) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
double loopTime = DIOJNI.getLoopTiming(status.asIntBuffer())/(kSystemClockTicksPerMicrosecond*1e3);
|
||||
|
||||
m_maxPwm = (int)((max-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
m_deadbandMaxPwm = (int)((deadbandMax-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
m_centerPwm = (int)((center-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
m_deadbandMinPwm = (int)((deadbandMin-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
m_minPwm = (int)((min-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the channel number associated with the PWM Object.
|
||||
*
|
||||
* @return The channel number.
|
||||
*/
|
||||
public int getChannel() {
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value based on a position.
|
||||
*
|
||||
* This is intended to be used by servos.
|
||||
*
|
||||
* @pre SetMaxPositivePwm() called.
|
||||
* @pre SetMinNegativePwm() called.
|
||||
*
|
||||
* @param pos The position to set the servo between 0.0 and 1.0.
|
||||
*/
|
||||
public void setPosition(double pos) {
|
||||
if (pos < 0.0) {
|
||||
pos = 0.0;
|
||||
} else if (pos > 1.0) {
|
||||
pos = 1.0;
|
||||
}
|
||||
|
||||
int rawValue;
|
||||
// note, need to perform the multiplication below as floating point before converting to int
|
||||
rawValue = (int) ((pos * (double)getFullRangeScaleFactor()) + getMinNegativePwm());
|
||||
|
||||
// send the computed pwm value to the FPGA
|
||||
setRaw(rawValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM value in terms of a position.
|
||||
*
|
||||
* This is intended to be used by servos.
|
||||
*
|
||||
* @pre SetMaxPositivePwm() called.
|
||||
* @pre SetMinNegativePwm() called.
|
||||
*
|
||||
* @return The position the servo is set to between 0.0 and 1.0.
|
||||
*/
|
||||
public double getPosition() {
|
||||
int value = getRaw();
|
||||
if (value < getMinNegativePwm()) {
|
||||
return 0.0;
|
||||
} else if (value > getMaxPositivePwm()) {
|
||||
return 1.0;
|
||||
} else {
|
||||
return (double)(value - getMinNegativePwm()) / (double)getFullRangeScaleFactor();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value based on a speed.
|
||||
*
|
||||
* This is intended to be used by speed controllers.
|
||||
*
|
||||
* @pre SetMaxPositivePwm() called.
|
||||
* @pre SetMinPositivePwm() called.
|
||||
* @pre SetCenterPwm() called.
|
||||
* @pre SetMaxNegativePwm() called.
|
||||
* @pre SetMinNegativePwm() called.
|
||||
*
|
||||
* @param speed The speed to set the speed controller between -1.0 and 1.0.
|
||||
*/
|
||||
final void setSpeed(double speed) {
|
||||
// clamp speed to be in the range 1.0 >= speed >= -1.0
|
||||
if (speed < -1.0) {
|
||||
speed = -1.0;
|
||||
} else if (speed > 1.0) {
|
||||
speed = 1.0;
|
||||
}
|
||||
|
||||
// calculate the desired output pwm value by scaling the speed appropriately
|
||||
int rawValue;
|
||||
if (speed == 0.0) {
|
||||
rawValue = getCenterPwm();
|
||||
} else if (speed > 0.0) {
|
||||
rawValue = (int) (speed * ((double)getPositiveScaleFactor()) +
|
||||
((double)getMinPositivePwm()) + 0.5);
|
||||
} else {
|
||||
rawValue = (int) (speed * ((double)getNegativeScaleFactor()) +
|
||||
((double)getMaxNegativePwm()) + 0.5);
|
||||
}
|
||||
|
||||
// send the computed pwm value to the FPGA
|
||||
setRaw(rawValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM value in terms of speed.
|
||||
*
|
||||
* This is intended to be used by speed controllers.
|
||||
*
|
||||
* @pre SetMaxPositivePwm() called.
|
||||
* @pre SetMinPositivePwm() called.
|
||||
* @pre SetMaxNegativePwm() called.
|
||||
* @pre SetMinNegativePwm() called.
|
||||
*
|
||||
* @return The most recently set speed between -1.0 and 1.0.
|
||||
*/
|
||||
public double getSpeed() {
|
||||
int value = getRaw();
|
||||
if (value > getMaxPositivePwm()) {
|
||||
return 1.0;
|
||||
} else if (value < getMinNegativePwm()) {
|
||||
return -1.0;
|
||||
} else if (value > getMinPositivePwm()) {
|
||||
return (double) (value - getMinPositivePwm()) / (double)getPositiveScaleFactor();
|
||||
} else if (value < getMaxNegativePwm()) {
|
||||
return (double) (value - getMaxNegativePwm()) / (double)getNegativeScaleFactor();
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value directly to the hardware.
|
||||
*
|
||||
* Write a raw value to a PWM channel.
|
||||
*
|
||||
* @param value Raw PWM value. Range 0 - 255.
|
||||
*/
|
||||
public void setRaw(int value) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
PWMJNI.setPWM(m_port, (short) value, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM value directly from the hardware.
|
||||
*
|
||||
* Read a raw value from a PWM channel.
|
||||
*
|
||||
* @return Raw PWM control value. Range: 0 - 255.
|
||||
*/
|
||||
public int getRaw() {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
int value = PWMJNI.getPWM(m_port, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Slow down the PWM signal for old devices.
|
||||
*
|
||||
* @param mult The period multiplier to apply to this channel
|
||||
*/
|
||||
public void setPeriodMultiplier(PeriodMultiplier mult) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
switch (mult.value) {
|
||||
case PeriodMultiplier.k4X_val:
|
||||
// Squelch 3 out of 4 outputs
|
||||
PWMJNI.setPWMPeriodScale(m_port, 3, status.asIntBuffer());
|
||||
break;
|
||||
case PeriodMultiplier.k2X_val:
|
||||
// Squelch 1 out of 2 outputs
|
||||
PWMJNI.setPWMPeriodScale(m_port, 1, status.asIntBuffer());
|
||||
break;
|
||||
case PeriodMultiplier.k1X_val:
|
||||
// Don't squelch any outputs
|
||||
PWMJNI.setPWMPeriodScale(m_port, 0, status.asIntBuffer());
|
||||
break;
|
||||
default:
|
||||
//Cannot hit this, limited by PeriodMultiplier enum
|
||||
}
|
||||
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
private int getMaxPositivePwm() {
|
||||
return m_maxPwm;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getMinPositivePwm() {
|
||||
return m_eliminateDeadband ? m_deadbandMaxPwm : m_centerPwm + 1;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getCenterPwm() {
|
||||
return m_centerPwm;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getMaxNegativePwm() {
|
||||
return m_eliminateDeadband ? m_deadbandMinPwm : m_centerPwm - 1;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getMinNegativePwm() {
|
||||
return m_minPwm;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getPositiveScaleFactor() {
|
||||
return getMaxPositivePwm() - getMinPositivePwm();
|
||||
} ///< The scale for positive speeds.
|
||||
|
||||
private int getNegativeScaleFactor() {
|
||||
return getMaxNegativePwm() - getMinNegativePwm();
|
||||
} ///< The scale for negative speeds.
|
||||
|
||||
private int getFullRangeScaleFactor() {
|
||||
return getMaxPositivePwm() - getMinNegativePwm();
|
||||
} ///< The scale for positions.
|
||||
|
||||
/*
|
||||
* XXX: Refactor to no longer depend on the DigitalModule, and move all
|
||||
* resource tracking into the HAL. This will wait until we get the unit
|
||||
* tests running for the first time.
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Speed Controller";
|
||||
}
|
||||
private ITable m_table;
|
||||
private ITableListener m_table_listener;
|
||||
|
||||
private static Resource allocated = new Resource( kPwmChannels);
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the amount to multiply the minimum servo-pulse pwm period by.
|
||||
*/
|
||||
public static class PeriodMultiplier {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Value", getSpeed());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int k1X_val = 1;
|
||||
static final int k2X_val = 2;
|
||||
static final int k4X_val = 4;
|
||||
/**
|
||||
* Period Multiplier: don't skip pulses
|
||||
*/
|
||||
public static final PeriodMultiplier k1X = new PeriodMultiplier(k1X_val);
|
||||
/**
|
||||
* Period Multiplier: skip every other pulse
|
||||
*/
|
||||
public static final PeriodMultiplier k2X = new PeriodMultiplier(k2X_val);
|
||||
/**
|
||||
* Period Multiplier: skip three out of four pulses
|
||||
*/
|
||||
public static final PeriodMultiplier k4X = new PeriodMultiplier(k4X_val);
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
private PeriodMultiplier(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
private int m_channel;
|
||||
private DigitalModule m_module;
|
||||
/**
|
||||
* kDefaultPwmPeriod is in ms
|
||||
*
|
||||
* - 20ms periods (50 Hz) are the "safest" setting in that this works for all devices
|
||||
* - 20ms periods seem to be desirable for Vex Motors
|
||||
* - 20ms periods are the specified period for HS-322HD servos, but work reliably down
|
||||
* to 10.0 ms; starting at about 8.5ms, the servo sometimes hums and get hot;
|
||||
* by 5.0ms the hum is nearly continuous
|
||||
* - 10ms periods work well for Victor 884
|
||||
* - 5ms periods allows higher update rates for Luminary Micro Jaguar speed controllers.
|
||||
* Due to the shipping firmware on the Jaguar, we can't run the update period less
|
||||
* than 5.05 ms.
|
||||
*
|
||||
* kDefaultPwmPeriod is the 1x period (5.05 ms). In hardware, the period scaling is implemented as an
|
||||
* output squelch to get longer periods for old devices.
|
||||
*/
|
||||
protected static final double kDefaultPwmPeriod = 5.05;
|
||||
/**
|
||||
* kDefaultPwmCenter is the PWM range center in ms
|
||||
*/
|
||||
protected static final double kDefaultPwmCenter = 1.5;
|
||||
/**
|
||||
* kDefaultPWMStepsDown is the number of PWM steps below the centerpoint
|
||||
*/
|
||||
protected static final int kDefaultPwmStepsDown = 1000;
|
||||
public static final int kPwmDisabled = 0;
|
||||
boolean m_eliminateDeadband;
|
||||
int m_maxPwm;
|
||||
int m_deadbandMaxPwm;
|
||||
int m_centerPwm;
|
||||
int m_deadbandMinPwm;
|
||||
int m_minPwm;
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
setSpeed(0); // Stop for safety
|
||||
m_table_listener = new ITableListener() {
|
||||
public void valueChanged(ITable itable, String key, Object value, boolean bln) {
|
||||
setSpeed(((Double) value).doubleValue());
|
||||
}
|
||||
};
|
||||
m_table.addTableListener("Value", m_table_listener, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize PWMs given a channel.
|
||||
*
|
||||
* This method is private and is the common path for all the constructors for creating PWM
|
||||
* instances. Checks module and channel value ranges and allocates the appropriate channel.
|
||||
* The allocation is only done to help users ensure that they don't double assign channels.
|
||||
*/
|
||||
private void initPWM(final int channel) {
|
||||
checkPWMChannel(channel);
|
||||
try {
|
||||
allocated.allocate(channel);
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException(
|
||||
"PWM channel " + channel + " is already allocated");
|
||||
}
|
||||
m_channel = channel;
|
||||
m_module = DigitalModule.getInstance(1);
|
||||
m_module.setPWM(m_channel, kPwmDisabled);
|
||||
m_eliminateDeadband = false;
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_PWM, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a PWM given a channel.
|
||||
*
|
||||
* @param channel The PWM channel.
|
||||
*/
|
||||
public PWM(final int channel) {
|
||||
initPWM(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the PWM channel.
|
||||
*
|
||||
* Free the resource associated with the PWM channel and set the value to 0.
|
||||
*/
|
||||
public void free() {
|
||||
m_module.setPWM(m_channel, kPwmDisabled);
|
||||
m_module.freeDIO(m_channel);
|
||||
allocated.free(m_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally eliminate the deadband from a speed controller.
|
||||
* @param eliminateDeadband If true, set the motor curve on the Jaguar to eliminate
|
||||
* the deadband in the middle of the range. Otherwise, keep the full range without
|
||||
* modifying any values.
|
||||
*/
|
||||
public void enableDeadbandElimination(boolean eliminateDeadband) {
|
||||
m_eliminateDeadband = eliminateDeadband;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bounds on the PWM values.
|
||||
* This sets the bounds on the PWM values for a particular each type of controller. The values
|
||||
* determine the upper and lower speeds as well as the deadband bracket.
|
||||
* @deprecated Recommended to set bounds in ms using {@link #setBounds(double, double, double, double, double)}
|
||||
* @param max The Minimum pwm value
|
||||
* @param deadbandMax The high end of the deadband range
|
||||
* @param center The center speed (off)
|
||||
* @param deadbandMin The low end of the deadband range
|
||||
* @param min The minimum pwm value
|
||||
*/
|
||||
public void setBounds(final int max, final int deadbandMax, final int center, final int deadbandMin, final int min) {
|
||||
m_maxPwm = max;
|
||||
m_deadbandMaxPwm = deadbandMax;
|
||||
m_centerPwm = center;
|
||||
m_deadbandMinPwm = deadbandMin;
|
||||
m_minPwm = min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bounds on the PWM pulse widths.
|
||||
* This sets the bounds on the PWM values for a particular type of controller. The values
|
||||
* determine the upper and lower speeds as well as the deadband bracket.
|
||||
* @param max The max PWM pulse width in ms
|
||||
* @param deadbandMax The high end of the deadband range pulse width in ms
|
||||
* @param center The center (off) pulse width in ms
|
||||
* @param deadbandMin The low end of the deadband pulse width in ms
|
||||
* @param min The minimum pulse width in ms
|
||||
*/
|
||||
protected void setBounds(double max, double deadbandMax, double center, double deadbandMin, double min) {
|
||||
double loopTime = m_module.getLoopTiming()/(kSystemClockTicksPerMicrosecond*1e3);
|
||||
|
||||
m_maxPwm = (int)((max-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
m_deadbandMaxPwm = (int)((deadbandMax-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
m_centerPwm = (int)((center-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
m_deadbandMinPwm = (int)((deadbandMin-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
m_minPwm = (int)((min-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the channel number associated with the PWM Object.
|
||||
*
|
||||
* @return The channel number.
|
||||
*/
|
||||
public int getChannel() {
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value based on a position.
|
||||
*
|
||||
* This is intended to be used by servos.
|
||||
*
|
||||
* @pre SetMaxPositivePwm() called.
|
||||
* @pre SetMinNegativePwm() called.
|
||||
*
|
||||
* @param pos The position to set the servo between 0.0 and 1.0.
|
||||
*/
|
||||
public void setPosition(double pos) {
|
||||
if (pos < 0.0) {
|
||||
pos = 0.0;
|
||||
} else if (pos > 1.0) {
|
||||
pos = 1.0;
|
||||
}
|
||||
|
||||
int rawValue;
|
||||
// note, need to perform the multiplication below as floating point before converting to int
|
||||
rawValue = (int) ((pos * (double)getFullRangeScaleFactor()) + getMinNegativePwm());
|
||||
|
||||
// send the computed pwm value to the FPGA
|
||||
setRaw(rawValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM value in terms of a position.
|
||||
*
|
||||
* This is intended to be used by servos.
|
||||
*
|
||||
* @pre SetMaxPositivePwm() called.
|
||||
* @pre SetMinNegativePwm() called.
|
||||
*
|
||||
* @return The position the servo is set to between 0.0 and 1.0.
|
||||
*/
|
||||
public double getPosition() {
|
||||
int value = getRaw();
|
||||
if (value < getMinNegativePwm()) {
|
||||
return 0.0;
|
||||
} else if (value > getMaxPositivePwm()) {
|
||||
return 1.0;
|
||||
} else {
|
||||
return (double)(value - getMinNegativePwm()) / (double)getFullRangeScaleFactor();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value based on a speed.
|
||||
*
|
||||
* This is intended to be used by speed controllers.
|
||||
*
|
||||
* @pre SetMaxPositivePwm() called.
|
||||
* @pre SetMinPositivePwm() called.
|
||||
* @pre SetCenterPwm() called.
|
||||
* @pre SetMaxNegativePwm() called.
|
||||
* @pre SetMinNegativePwm() called.
|
||||
*
|
||||
* @param speed The speed to set the speed controller between -1.0 and 1.0.
|
||||
*/
|
||||
final void setSpeed(double speed) {
|
||||
// clamp speed to be in the range 1.0 >= speed >= -1.0
|
||||
if (speed < -1.0) {
|
||||
speed = -1.0;
|
||||
} else if (speed > 1.0) {
|
||||
speed = 1.0;
|
||||
}
|
||||
|
||||
// calculate the desired output pwm value by scaling the speed appropriately
|
||||
int rawValue;
|
||||
if (speed == 0.0) {
|
||||
rawValue = getCenterPwm();
|
||||
} else if (speed > 0.0) {
|
||||
rawValue = (int) (speed * ((double)getPositiveScaleFactor()) +
|
||||
((double)getMinPositivePwm()) + 0.5);
|
||||
} else {
|
||||
rawValue = (int) (speed * ((double)getNegativeScaleFactor()) +
|
||||
((double)getMaxNegativePwm()) + 0.5);
|
||||
}
|
||||
|
||||
// send the computed pwm value to the FPGA
|
||||
setRaw(rawValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM value in terms of speed.
|
||||
*
|
||||
* This is intended to be used by speed controllers.
|
||||
*
|
||||
* @pre SetMaxPositivePwm() called.
|
||||
* @pre SetMinPositivePwm() called.
|
||||
* @pre SetMaxNegativePwm() called.
|
||||
* @pre SetMinNegativePwm() called.
|
||||
*
|
||||
* @return The most recently set speed between -1.0 and 1.0.
|
||||
*/
|
||||
public double getSpeed() {
|
||||
int value = getRaw();
|
||||
if (value > getMaxPositivePwm()) {
|
||||
return 1.0;
|
||||
} else if (value < getMinNegativePwm()) {
|
||||
return -1.0;
|
||||
} else if (value > getMinPositivePwm()) {
|
||||
return (double) (value - getMinPositivePwm()) / (double)getPositiveScaleFactor();
|
||||
} else if (value < getMaxNegativePwm()) {
|
||||
return (double) (value - getMaxNegativePwm()) / (double)getNegativeScaleFactor();
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value directly to the hardware.
|
||||
*
|
||||
* Write a raw value to a PWM channel.
|
||||
*
|
||||
* @param value Raw PWM value. Range 0 - 255.
|
||||
*/
|
||||
public void setRaw(int value) {
|
||||
m_module.setPWM(m_channel, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM value directly from the hardware.
|
||||
*
|
||||
* Read a raw value from a PWM channel.
|
||||
*
|
||||
* @return Raw PWM control value. Range: 0 - 255.
|
||||
*/
|
||||
public int getRaw() {
|
||||
return m_module.getPWM(m_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Slow down the PWM signal for old devices.
|
||||
*
|
||||
* @param mult The period multiplier to apply to this channel
|
||||
*/
|
||||
public void setPeriodMultiplier(PeriodMultiplier mult) {
|
||||
switch (mult.value) {
|
||||
case PeriodMultiplier.k4X_val:
|
||||
m_module.setPWMPeriodScale(m_channel, 3); // Squelch 3 out of 4 outputs
|
||||
break;
|
||||
case PeriodMultiplier.k2X_val:
|
||||
m_module.setPWMPeriodScale(m_channel, 1); // Squelch 1 out of 2 outputs
|
||||
break;
|
||||
case PeriodMultiplier.k1X_val:
|
||||
m_module.setPWMPeriodScale(m_channel, 0); // Don't squelch any outputs
|
||||
break;
|
||||
default:
|
||||
//Cannot hit this, limited by PeriodMultiplier enum
|
||||
}
|
||||
}
|
||||
|
||||
private int getMaxPositivePwm() {
|
||||
return m_maxPwm;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getMinPositivePwm() {
|
||||
return m_eliminateDeadband ? m_deadbandMaxPwm : m_centerPwm + 1;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getCenterPwm() {
|
||||
return m_centerPwm;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getMaxNegativePwm() {
|
||||
return m_eliminateDeadband ? m_deadbandMinPwm : m_centerPwm - 1;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getMinNegativePwm() {
|
||||
return m_minPwm;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getPositiveScaleFactor() {
|
||||
return getMaxPositivePwm() - getMinPositivePwm();
|
||||
} ///< The scale for positive speeds.
|
||||
|
||||
private int getNegativeScaleFactor() {
|
||||
return getMaxNegativePwm() - getMinNegativePwm();
|
||||
} ///< The scale for negative speeds.
|
||||
|
||||
private int getFullRangeScaleFactor() {
|
||||
return getMaxPositivePwm() - getMinNegativePwm();
|
||||
} ///< The scale for positions.
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Speed Controller";
|
||||
}
|
||||
private ITable m_table;
|
||||
private ITableListener m_table_listener;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Value", getSpeed());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
setSpeed(0); // Stop for safety
|
||||
m_table_listener = new ITableListener() {
|
||||
public void valueChanged(ITable itable, String key, Object value, boolean bln) {
|
||||
setSpeed(((Double) value).doubleValue());
|
||||
}
|
||||
};
|
||||
m_table.addTableListener("Value", m_table_listener, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
setSpeed(0); // Stop for safety
|
||||
// TODO: Broken, should only remove the listener from "Value" only.
|
||||
m_table.removeTableListener(m_table_listener);
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
setSpeed(0); // Stop for safety
|
||||
// TODO: Broken, should only remove the listener from "Value" only.
|
||||
m_table.removeTableListener(m_table_listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,15 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.DIOJNI;
|
||||
import edu.wpi.first.wpilibj.hal.RelayJNI;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.parsing.IDeviceController;
|
||||
@@ -113,8 +119,8 @@ public class Relay extends SensorBase implements IDeviceController,
|
||||
}
|
||||
|
||||
private int m_channel;
|
||||
private ByteBuffer m_port;
|
||||
private Direction m_direction;
|
||||
private DigitalModule m_module;
|
||||
private static Resource relayChannels = new Resource(kRelayChannels * 2);
|
||||
|
||||
/**
|
||||
@@ -138,9 +144,13 @@ public class Relay extends SensorBase implements IDeviceController,
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException("Relay channel " + m_channel + " is already allocated");
|
||||
}
|
||||
m_module = DigitalModule.getInstance(1);
|
||||
m_module.setRelayForward(m_channel, false);
|
||||
m_module.setRelayReverse(m_channel, false);
|
||||
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
m_port = DIOJNI.initializeDigitalPort(DIOJNI.getPort((byte) m_channel), status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
|
||||
LiveWindow.addActuator("Relay", m_channel, this);
|
||||
}
|
||||
|
||||
@@ -173,21 +183,22 @@ public class Relay extends SensorBase implements IDeviceController,
|
||||
}
|
||||
|
||||
public void free() {
|
||||
m_module.setRelayForward(m_channel, false);
|
||||
m_module.setRelayReverse(m_channel, false);
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
RelayJNI.setRelayForward(m_port, (byte) 0, status.asIntBuffer());
|
||||
RelayJNI.setRelayForward(m_port, (byte) 0, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
|
||||
if (m_direction == Direction.kBoth || m_direction == Direction.kForward) {
|
||||
relayChannels.free(((m_module.getModuleNumber() - 1)
|
||||
* kRelayChannels + m_channel) * 2);
|
||||
m_module.freeDIO(((m_module.getModuleNumber() - 1) * kRelayChannels
|
||||
+ m_channel) * 2);
|
||||
relayChannels.free(m_channel);
|
||||
}
|
||||
if (m_direction == Direction.kBoth || m_direction == Direction.kReverse) {
|
||||
relayChannels.free(((m_module.getModuleNumber() - 1)
|
||||
* kRelayChannels + m_channel) * 2 + 1);
|
||||
m_module.freeDIO(((m_module.getModuleNumber() - 1) * kRelayChannels
|
||||
+ m_channel) * 2 + 1);
|
||||
relayChannels.free(m_channel + 1);
|
||||
}
|
||||
|
||||
DIOJNI.freeDIO(m_port, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,25 +218,28 @@ public class Relay extends SensorBase implements IDeviceController,
|
||||
* The state to set the relay.
|
||||
*/
|
||||
public void set(Value value) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
switch (value.value) {
|
||||
case Value.kOff_val:
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kForward) {
|
||||
m_module.setRelayForward(m_channel, false);
|
||||
RelayJNI.setRelayForward(m_port, (byte) 0, status.asIntBuffer());
|
||||
}
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kReverse) {
|
||||
m_module.setRelayReverse(m_channel, false);
|
||||
RelayJNI.setRelayReverse(m_port, (byte) 0, status.asIntBuffer());
|
||||
}
|
||||
break;
|
||||
case Value.kOn_val:
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kForward) {
|
||||
m_module.setRelayForward(m_channel, true);
|
||||
RelayJNI.setRelayForward(m_port, (byte) 1, status.asIntBuffer());
|
||||
}
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kReverse) {
|
||||
m_module.setRelayReverse(m_channel, true);
|
||||
RelayJNI.setRelayReverse(m_port, (byte) 1, status.asIntBuffer());
|
||||
}
|
||||
break;
|
||||
case Value.kForward_val:
|
||||
@@ -234,10 +248,10 @@ public class Relay extends SensorBase implements IDeviceController,
|
||||
"A relay configured for reverse cannot be set to forward");
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kForward) {
|
||||
m_module.setRelayForward(m_channel, true);
|
||||
RelayJNI.setRelayForward(m_port, (byte) 1, status.asIntBuffer());
|
||||
}
|
||||
if (m_direction == Direction.kBoth) {
|
||||
m_module.setRelayReverse(m_channel, false);
|
||||
RelayJNI.setRelayReverse(m_port, (byte) 0, status.asIntBuffer());
|
||||
}
|
||||
break;
|
||||
case Value.kReverse_val:
|
||||
@@ -245,16 +259,18 @@ public class Relay extends SensorBase implements IDeviceController,
|
||||
throw new InvalidValueException(
|
||||
"A relay configured for forward cannot be set to reverse");
|
||||
if (m_direction == Direction.kBoth) {
|
||||
m_module.setRelayForward(m_channel, false);
|
||||
RelayJNI.setRelayForward(m_port, (byte) 0, status.asIntBuffer());
|
||||
}
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kReverse) {
|
||||
m_module.setRelayReverse(m_channel, true);
|
||||
RelayJNI.setRelayReverse(m_port, (byte) 1, status.asIntBuffer());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Cannot hit this, limited by Value enum
|
||||
}
|
||||
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,8 +284,11 @@ public class Relay extends SensorBase implements IDeviceController,
|
||||
* @return The current state of the relay as a Relay::Value
|
||||
*/
|
||||
public Value get() {
|
||||
if (m_module.getRelayForward(m_channel)) {
|
||||
if (m_module.getRelayReverse(m_channel)) {
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
if (RelayJNI.getRelayForward(m_port, status.asIntBuffer()) != 0) {
|
||||
if (RelayJNI.getRelayReverse(m_port, status.asIntBuffer()) != 0) {
|
||||
return Value.kOn;
|
||||
} else {
|
||||
if (m_direction == Direction.kForward) {
|
||||
@@ -279,7 +298,7 @@ public class Relay extends SensorBase implements IDeviceController,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m_module.getRelayReverse(m_channel)) {
|
||||
if (RelayJNI.getRelayReverse(m_port, status.asIntBuffer()) != 0) {
|
||||
if (m_direction == Direction.kForward) {
|
||||
return Value.kOn;
|
||||
} else {
|
||||
|
||||
@@ -14,8 +14,6 @@ import edu.wpi.first.wpilibj.hal.AnalogJNI;
|
||||
* Base class for all sensors.
|
||||
* Stores most recent status information as well as containing utility functions for checking
|
||||
* channels and error processing.
|
||||
*
|
||||
* XXX: Wait, there's no exception thrown if we try to allocate a non-existent module? It that behavior correct?
|
||||
*/
|
||||
public abstract class SensorBase { // TODO: Refactor
|
||||
|
||||
@@ -30,28 +28,19 @@ public abstract class SensorBase { // TODO: Refactor
|
||||
*/
|
||||
public static final int kDigitalChannels = 26;
|
||||
/**
|
||||
* Number of digital modules
|
||||
* XXX: This number is incorrect. We need to find the correct number.
|
||||
*/
|
||||
public static final int kDigitalModules = 1;
|
||||
/**
|
||||
* Number of analog input channels per module
|
||||
* Number of analog input channels
|
||||
*/
|
||||
public static final int kAnalogInputChannels = 8;
|
||||
/**
|
||||
* Number of analog output channels per module
|
||||
* Number of analog output channels
|
||||
*/
|
||||
public static final int kAnalogOutputChannels = 2;
|
||||
/**
|
||||
* Number of analog modules
|
||||
*/
|
||||
public static final int kAnalogModules = 1;
|
||||
/**
|
||||
* Number of solenoid channels per module
|
||||
*/
|
||||
public static final int kSolenoidChannels = 8;
|
||||
/**
|
||||
* Number of analog modules
|
||||
* Number of solenoid modules
|
||||
*/
|
||||
public static final int kSolenoidModules = 2;
|
||||
/**
|
||||
@@ -67,8 +56,6 @@ public abstract class SensorBase { // TODO: Refactor
|
||||
*/
|
||||
public static final int kPDPChannels = 16;
|
||||
|
||||
private static int m_defaultAnalogModule = 1;
|
||||
private static int m_defaultDigitalModule = 1;
|
||||
private static int m_defaultSolenoidModule = 0;
|
||||
|
||||
/**
|
||||
@@ -78,33 +65,7 @@ public abstract class SensorBase { // TODO: Refactor
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default Digital Module.
|
||||
* This sets the default digital module to use for objects that are created without
|
||||
* specifying the digital module in the constructor. The default module is initialized
|
||||
* to the first module in the chassis.
|
||||
*
|
||||
* @param moduleNumber The number of the digital module to use.
|
||||
*/
|
||||
public static void setDefaultDigitalModule(final int moduleNumber) {
|
||||
checkDigitalModule(moduleNumber);
|
||||
SensorBase.m_defaultDigitalModule = moduleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default Analog module.
|
||||
* This sets the default analog module to use for objects that are created without
|
||||
* specifying the analog module in the constructor. The default module is initialized
|
||||
* to the first module in the chassis.
|
||||
*
|
||||
* @param moduleNumber The number of the analog module to use.
|
||||
*/
|
||||
public static void setDefaultAnalogModule(final int moduleNumber) {
|
||||
checkAnalogModule(moduleNumber);
|
||||
SensorBase.m_defaultAnalogModule = moduleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default location for the Solenoid (9472) module.
|
||||
* Set the default location for the Solenoid module.
|
||||
*
|
||||
* @param moduleNumber The number of the solenoid module to use.
|
||||
*/
|
||||
@@ -113,49 +74,6 @@ public abstract class SensorBase { // TODO: Refactor
|
||||
SensorBase.m_defaultSolenoidModule = moduleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the digital module number is valid.
|
||||
* Module numbers are 1 or 2 (they are no longer real cRIO slots).
|
||||
*
|
||||
* @param moduleNumber The digital module module number to check.
|
||||
*/
|
||||
protected static void checkDigitalModule(final int moduleNumber) {
|
||||
if(DIOJNI.checkDigitalModule((byte) moduleNumber) != 1)
|
||||
System.err.println("Digital module " + moduleNumber + " is not present.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the digital module number is valid.
|
||||
* Module numbers are 1 or 2 (they are no longer real cRIO slots).
|
||||
*
|
||||
* @param moduleNumber The digital module module number to check.
|
||||
*/
|
||||
protected static void checkRelayModule(final int moduleNumber) {
|
||||
checkDigitalModule(moduleNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the digital module number is valid.
|
||||
* Module numbers are 1 or 2 (they are no longer real cRIO slots).
|
||||
*
|
||||
* @param moduleNumber The digital module module number to check.
|
||||
*/
|
||||
protected static void checkPWMModule(final int moduleNumber) {
|
||||
checkDigitalModule(moduleNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the analog module number is valid.
|
||||
* Module numbers are 1 or 2 (they are no longer real cRIO slots).
|
||||
*
|
||||
* @param moduleNumber The analog module module number to check.
|
||||
*/
|
||||
protected static void checkAnalogModule(final int moduleNumber) {
|
||||
if(AnalogJNI.checkAnalogModule((byte) (moduleNumber - 1)) != 0) {
|
||||
System.err.println("Analog module " + moduleNumber + " is not present.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the solenoid module is correct.
|
||||
* Module numbers are 1 or 2 (they are no longer real cRIO slots).
|
||||
@@ -260,25 +178,7 @@ public abstract class SensorBase { // TODO: Refactor
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of the default analog module.
|
||||
*
|
||||
* @return The number of the default analog module.
|
||||
*/
|
||||
public static int getDefaultAnalogModule() {
|
||||
return SensorBase.m_defaultAnalogModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of the default analog module.
|
||||
*
|
||||
* @return The number of the default analog module.
|
||||
*/
|
||||
public static int getDefaultDigitalModule() {
|
||||
return SensorBase.m_defaultDigitalModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of the default analog module.
|
||||
* Get the number of the default solenoid module.
|
||||
*
|
||||
* @return The number of the default analog module.
|
||||
*/
|
||||
|
||||
@@ -22,14 +22,14 @@ import edu.wpi.first.wpilibj.util.AllocationException;
|
||||
import edu.wpi.first.wpilibj.util.CheckedAllocationException;
|
||||
|
||||
/**
|
||||
* Solenoid class for running high voltage Digital Output (9472 module).
|
||||
* Solenoid class for running high voltage Digital Output.
|
||||
*
|
||||
* The Solenoid class is typically used for pneumatics solenoids, but could be used
|
||||
* for any device within the current spec of the 9472 module.
|
||||
* for any device within the current spec of the PCM.
|
||||
*/
|
||||
public class Solenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
|
||||
private int m_channel; ///< The channel on the module to control.
|
||||
private int m_channel; ///< The channel to control.
|
||||
private ByteBuffer m_solenoid_port;
|
||||
|
||||
/**
|
||||
@@ -39,16 +39,9 @@ public class Solenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
checkSolenoidModule(m_moduleNumber);
|
||||
checkSolenoidChannel(m_channel);
|
||||
|
||||
// try {
|
||||
// m_allocated.allocate((m_moduleNumber - 1) * kSolenoidChannels + m_channel - 1);
|
||||
// } catch (CheckedAllocationException e) {
|
||||
// throw new AllocationException(
|
||||
// "Solenoid channel " + m_channel + " on module " + m_moduleNumber + " is already allocated");
|
||||
// }
|
||||
|
||||
ByteBuffer status = ByteBuffer.allocateDirect(4);
|
||||
status.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
|
||||
ByteBuffer port = SolenoidJNI.getPortWithModule((byte) m_moduleNumber, (byte) m_channel);
|
||||
m_solenoid_port = SolenoidJNI.initializeSolenoidPort(port, status.asIntBuffer());
|
||||
HALUtil.checkStatus(status.asIntBuffer());
|
||||
|
||||
@@ -162,8 +162,7 @@ public class Ultrasonic extends SensorBase implements PIDSource, ISensor,
|
||||
/**
|
||||
* Create an instance of the Ultrasonic Sensor.
|
||||
* This is designed to supchannel the Daventech SRF04 and Vex ultrasonic
|
||||
* sensors. This constructor assumes that both digital I/O channels are in
|
||||
* the default digital module. Default unit is inches.
|
||||
* sensors. Default unit is inches.
|
||||
*
|
||||
* @param pingChannel
|
||||
* The digital output channel that sends the pulse to initiate
|
||||
|
||||
@@ -23,33 +23,33 @@ public class JNIWrapper
|
||||
jniLibrary = File.createTempFile("libwpilibJavaJNI", ".so");
|
||||
// flag for delete on exit
|
||||
jniLibrary.deleteOnExit();
|
||||
|
||||
|
||||
byte [] buffer = new byte[1024];
|
||||
|
||||
|
||||
int readBytes;
|
||||
|
||||
|
||||
InputStream is = JNIWrapper.class.getResourceAsStream("/linux-arm/libwpilibJavaJNI.so");
|
||||
|
||||
|
||||
OutputStream os = new FileOutputStream(jniLibrary);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
while((readBytes = is.read(buffer)) != -1 )
|
||||
{
|
||||
os.write(buffer, 0, readBytes);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
os.close();
|
||||
is.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
libraryLoaded = true;
|
||||
}
|
||||
|
||||
|
||||
System.load(jniLibrary.getAbsolutePath());
|
||||
}
|
||||
catch( Exception ex )
|
||||
@@ -59,4 +59,5 @@ public class JNIWrapper
|
||||
}
|
||||
}
|
||||
public static native ByteBuffer getPortWithModule(byte module, byte pin);
|
||||
public static native ByteBuffer getPort(byte pin);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user