mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-29 02:21:44 +00:00
Moves Encoders to Handles and Moves WPILib Encoders to HAL (#124)
This commit is contained in:
committed by
Peter Johnson
parent
b45e0917ae
commit
36ac37db8c
@@ -19,7 +19,7 @@ enum Mode {
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
HalCounterHandle initializeCounter(Mode mode, uint32_t* index, int32_t* status);
|
||||
HalCounterHandle initializeCounter(Mode mode, int32_t* index, int32_t* status);
|
||||
void freeCounter(HalCounterHandle counter_handle, int32_t* status);
|
||||
void setCounterAverageSize(HalCounterHandle counter_handle, int32_t size,
|
||||
int32_t* status);
|
||||
|
||||
@@ -9,26 +9,57 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "HAL/Handles.h"
|
||||
|
||||
extern "C" {
|
||||
void* initializeEncoder(uint8_t port_a_module, uint32_t port_a_pin,
|
||||
bool port_a_analog_trigger, uint8_t port_b_module,
|
||||
uint32_t port_b_pin, bool port_b_analog_trigger,
|
||||
bool reverseDirection, int32_t* index,
|
||||
int32_t* status); // TODO: fix routing
|
||||
void freeEncoder(void* encoder_pointer, int32_t* status);
|
||||
void resetEncoder(void* encoder_pointer, int32_t* status);
|
||||
int32_t getEncoder(void* encoder_pointer, int32_t* status); // Raw value
|
||||
double getEncoderPeriod(void* encoder_pointer, int32_t* status);
|
||||
void setEncoderMaxPeriod(void* encoder_pointer, double maxPeriod,
|
||||
int32_t* status);
|
||||
bool getEncoderStopped(void* encoder_pointer, int32_t* status);
|
||||
bool getEncoderDirection(void* encoder_pointer, int32_t* status);
|
||||
void setEncoderReverseDirection(void* encoder_pointer, bool reverseDirection,
|
||||
enum EncoderIndexingType {
|
||||
HAL_kResetWhileHigh,
|
||||
HAL_kResetWhileLow,
|
||||
HAL_kResetOnFallingEdge,
|
||||
HAL_kResetOnRisingEdge
|
||||
};
|
||||
enum EncoderEncodingType { HAL_Encoder_k1X, HAL_Encoder_k2X, HAL_Encoder_k4X };
|
||||
|
||||
HalEncoderHandle initializeEncoder(
|
||||
uint8_t port_a_module, uint32_t port_a_pin, bool port_a_analog_trigger,
|
||||
uint8_t port_b_module, uint32_t port_b_pin, bool port_b_analog_trigger,
|
||||
bool reverseDirection, EncoderEncodingType encodingType, int32_t* status);
|
||||
void freeEncoder(HalEncoderHandle encoder_handle, int32_t* status);
|
||||
int32_t getEncoder(HalEncoderHandle encoder_handle, int32_t* status);
|
||||
int32_t getEncoderRaw(HalEncoderHandle encoder_handle, int32_t* status);
|
||||
int32_t getEncoderEncodingScale(HalEncoderHandle encoder_handle,
|
||||
int32_t* status);
|
||||
void setEncoderSamplesToAverage(void* encoder_pointer,
|
||||
uint32_t samplesToAverage, int32_t* status);
|
||||
uint32_t getEncoderSamplesToAverage(void* encoder_pointer, int32_t* status);
|
||||
void setEncoderIndexSource(void* encoder_pointer, uint32_t pin,
|
||||
bool analogTrigger, bool activeHigh,
|
||||
bool edgeSensitive, int32_t* status);
|
||||
void resetEncoder(HalEncoderHandle encoder_handle, int32_t* status);
|
||||
int32_t getEncoderPeriod(HalEncoderHandle encoder_handle, int32_t* status);
|
||||
void setEncoderMaxPeriod(HalEncoderHandle encoder_handle, double maxPeriod,
|
||||
int32_t* status);
|
||||
uint8_t getEncoderStopped(HalEncoderHandle encoder_handle, int32_t* status);
|
||||
uint8_t getEncoderDirection(HalEncoderHandle encoder_handle, int32_t* status);
|
||||
double getEncoderDistance(HalEncoderHandle encoder_handle, int32_t* status);
|
||||
double getEncoderRate(HalEncoderHandle encoder_handle, int32_t* status);
|
||||
void setEncoderMinRate(HalEncoderHandle encoder_handle, double minRate,
|
||||
int32_t* status);
|
||||
void setEncoderDistancePerPulse(HalEncoderHandle encoder_handle,
|
||||
double distancePerPulse, int32_t* status);
|
||||
void setEncoderReverseDirection(HalEncoderHandle encoder_handle,
|
||||
uint8_t reverseDirection, int32_t* status);
|
||||
void setEncoderSamplesToAverage(HalEncoderHandle encoder_handle,
|
||||
int32_t samplesToAverage, int32_t* status);
|
||||
int32_t getEncoderSamplesToAverage(HalEncoderHandle encoder_handle,
|
||||
int32_t* status);
|
||||
|
||||
void setEncoderIndexSource(HalEncoderHandle encoder_handle, uint32_t pin,
|
||||
uint8_t analogTrigger, EncoderIndexingType type,
|
||||
int32_t* status);
|
||||
|
||||
int32_t getEncoderFPGAIndex(HalEncoderHandle encoder_handle, int32_t* status);
|
||||
|
||||
double getEncoderDecodingScaleFactor(HalEncoderHandle encoder_handle,
|
||||
int32_t* status);
|
||||
|
||||
double getEncoderDistancePerPulse(HalEncoderHandle encoder_handle,
|
||||
int32_t* status);
|
||||
|
||||
EncoderEncodingType getEncoderEncodingType(HalEncoderHandle encoder_handle,
|
||||
int32_t* status);
|
||||
}
|
||||
|
||||
@@ -67,6 +67,9 @@
|
||||
#define PARAMETER_OUT_OF_RANGE_MESSAGE "HAL: A parameter is out of range."
|
||||
#define RESOURCE_IS_ALLOCATED -1029
|
||||
#define RESOURCE_IS_ALLOCATED_MESSAGE "HAL: Resource already allocated"
|
||||
#define HAL_COUNTER_NOT_SUPPORTED -1058
|
||||
#define HAL_COUNTER_NOT_SUPPORTED_MESSAGE \
|
||||
"HAL: Counter mode not supported for encoder method"
|
||||
|
||||
#define VI_ERROR_SYSTEM_ERROR_MESSAGE "HAL - VISA: System Error";
|
||||
#define VI_ERROR_INV_OBJECT_MESSAGE "HAL - VISA: Invalid Object"
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "Compressor.h"
|
||||
#include "Counter.h"
|
||||
#include "DIO.h"
|
||||
#include "Encoder.h"
|
||||
#include "Errors.h"
|
||||
#include "FRC_NetworkCommunication/UsageReporting.h"
|
||||
#include "Handles.h"
|
||||
|
||||
@@ -36,3 +36,7 @@ typedef HalHandle HalCounterHandle;
|
||||
typedef HalHandle HalCompressorHandle;
|
||||
|
||||
typedef HalHandle HalSolenoidHandle;
|
||||
|
||||
typedef HalHandle HalFPGAEncoderHandle;
|
||||
|
||||
typedef HalHandle HalEncoderHandle;
|
||||
|
||||
@@ -26,8 +26,7 @@ static LimitedHandleResource<HalCounterHandle, Counter, kNumCounters,
|
||||
counterHandles;
|
||||
|
||||
extern "C" {
|
||||
HalCounterHandle initializeCounter(Mode mode, uint32_t* index,
|
||||
int32_t* status) {
|
||||
HalCounterHandle initializeCounter(Mode mode, int32_t* index, int32_t* status) {
|
||||
auto handle = counterHandles.Allocate();
|
||||
if (handle == HAL_INVALID_HANDLE) { // out of resources
|
||||
*status = NO_AVAILABLE_RESOURCES;
|
||||
|
||||
@@ -7,202 +7,428 @@
|
||||
|
||||
#include "HAL/Encoder.h"
|
||||
|
||||
#include "DigitalInternal.h"
|
||||
#include "HAL/cpp/Resource.h"
|
||||
|
||||
static_assert(sizeof(uint32_t) <= sizeof(void*),
|
||||
"This file shoves uint32_ts into pointers.");
|
||||
#include "ChipObject.h"
|
||||
#include "EncoderInternal.h"
|
||||
#include "FPGAEncoder.h"
|
||||
#include "HAL/Counter.h"
|
||||
#include "HAL/Errors.h"
|
||||
#include "handles/LimitedClassedHandleResource.h"
|
||||
|
||||
using namespace hal;
|
||||
|
||||
extern "C" {
|
||||
struct encoder_t {
|
||||
tEncoder* encoder;
|
||||
uint32_t index;
|
||||
};
|
||||
typedef struct encoder_t Encoder;
|
||||
Encoder::Encoder(uint8_t port_a_module, uint32_t port_a_pin,
|
||||
bool port_a_analog_trigger, uint8_t port_b_module,
|
||||
uint32_t port_b_pin, bool port_b_analog_trigger,
|
||||
bool reverseDirection, EncoderEncodingType encodingType,
|
||||
int32_t* status) {
|
||||
m_encodingType = encodingType;
|
||||
switch (encodingType) {
|
||||
case HAL_Encoder_k4X: {
|
||||
m_encodingScale = 4;
|
||||
m_encoder = initializeFPGAEncoder(port_a_module, port_a_pin,
|
||||
port_a_analog_trigger, port_b_module,
|
||||
port_b_pin, port_b_analog_trigger,
|
||||
reverseDirection, &m_index, status);
|
||||
if (*status != 0) {
|
||||
return;
|
||||
}
|
||||
m_counter = HAL_INVALID_HANDLE;
|
||||
SetMaxPeriod(.5, status);
|
||||
break;
|
||||
}
|
||||
case HAL_Encoder_k1X:
|
||||
case HAL_Encoder_k2X: {
|
||||
SetupCounter(port_a_module, port_a_pin, port_a_analog_trigger,
|
||||
port_b_module, port_b_pin, port_b_analog_trigger,
|
||||
reverseDirection, encodingType, status);
|
||||
|
||||
static const double DECODING_SCALING_FACTOR = 0.25;
|
||||
static hal::Resource* quadEncoders = nullptr;
|
||||
|
||||
void* initializeEncoder(uint8_t port_a_module, uint32_t port_a_pin,
|
||||
bool port_a_analog_trigger, uint8_t port_b_module,
|
||||
uint32_t port_b_pin, bool port_b_analog_trigger,
|
||||
bool reverseDirection, int32_t* index,
|
||||
int32_t* status) {
|
||||
// Initialize encoder structure
|
||||
Encoder* encoder = new Encoder();
|
||||
|
||||
remapDigitalSource(port_a_analog_trigger, port_a_pin, port_a_module);
|
||||
remapDigitalSource(port_b_analog_trigger, port_b_pin, port_b_module);
|
||||
|
||||
hal::Resource::CreateResourceObject(&quadEncoders, tEncoder::kNumSystems);
|
||||
encoder->index = quadEncoders->Allocate("4X Encoder");
|
||||
*index = encoder->index;
|
||||
// TODO: if (index == ~0ul) { CloneError(quadEncoders); return; }
|
||||
encoder->encoder = tEncoder::create(encoder->index, status);
|
||||
encoder->encoder->writeConfig_ASource_Module(port_a_module, status);
|
||||
encoder->encoder->writeConfig_ASource_Channel(port_a_pin, status);
|
||||
encoder->encoder->writeConfig_ASource_AnalogTrigger(port_a_analog_trigger,
|
||||
status);
|
||||
encoder->encoder->writeConfig_BSource_Module(port_b_module, status);
|
||||
encoder->encoder->writeConfig_BSource_Channel(port_b_pin, status);
|
||||
encoder->encoder->writeConfig_BSource_AnalogTrigger(port_b_analog_trigger,
|
||||
status);
|
||||
encoder->encoder->strobeReset(status);
|
||||
encoder->encoder->writeConfig_Reverse(reverseDirection, status);
|
||||
encoder->encoder->writeTimerConfig_AverageSize(4, status);
|
||||
|
||||
return encoder;
|
||||
}
|
||||
|
||||
void freeEncoder(void* encoder_pointer, int32_t* status) {
|
||||
Encoder* encoder = (Encoder*)encoder_pointer;
|
||||
if (!encoder) return;
|
||||
quadEncoders->Free(encoder->index);
|
||||
delete encoder->encoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the Encoder distance to zero.
|
||||
* Resets the current count to zero on the encoder.
|
||||
*/
|
||||
void resetEncoder(void* encoder_pointer, int32_t* status) {
|
||||
Encoder* encoder = (Encoder*)encoder_pointer;
|
||||
encoder->encoder->strobeReset(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw value from the encoder.
|
||||
* The raw value is the actual count unscaled by the 1x, 2x, or 4x scale
|
||||
* factor.
|
||||
* @return Current raw count from the encoder
|
||||
*/
|
||||
int32_t getEncoder(void* encoder_pointer, int32_t* status) {
|
||||
Encoder* encoder = (Encoder*)encoder_pointer;
|
||||
return encoder->encoder->readOutput_Value(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the period of the most recent pulse.
|
||||
* Returns the period of the most recent Encoder pulse in seconds.
|
||||
* This method compenstates for the decoding type.
|
||||
*
|
||||
* @deprecated Use GetRate() in favor of this method. This returns unscaled
|
||||
* periods and GetRate() scales using value from SetDistancePerPulse().
|
||||
*
|
||||
* @return Period in seconds of the most recent pulse.
|
||||
*/
|
||||
double getEncoderPeriod(void* encoder_pointer, int32_t* status) {
|
||||
Encoder* encoder = (Encoder*)encoder_pointer;
|
||||
tEncoder::tTimerOutput output = encoder->encoder->readTimerOutput(status);
|
||||
double value;
|
||||
if (output.Stalled) {
|
||||
// Return infinity
|
||||
double zero = 0.0;
|
||||
value = 1.0 / zero;
|
||||
} else {
|
||||
// output.Period is a fixed point number that counts by 2 (24 bits, 25
|
||||
// integer bits)
|
||||
value = (double)(output.Period << 1) / (double)output.Count;
|
||||
m_encodingScale = encodingType == HAL_Encoder_k1X ? 1 : 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
double measuredPeriod = value * 2.5e-8;
|
||||
return measuredPeriod / DECODING_SCALING_FACTOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum period for stopped detection.
|
||||
* Sets the value that represents the maximum period of the Encoder before it
|
||||
* will assume that the attached device is stopped. This timeout allows users
|
||||
* to determine if the wheels or other shaft has stopped rotating.
|
||||
* This method compensates for the decoding type.
|
||||
*
|
||||
* @deprecated Use SetMinRate() in favor of this method. This takes unscaled
|
||||
* periods and SetMinRate() scales using value from SetDistancePerPulse().
|
||||
*
|
||||
* @param maxPeriod The maximum time between rising and falling edges before the
|
||||
* FPGA will
|
||||
* report the device stopped. This is expressed in seconds.
|
||||
*/
|
||||
void setEncoderMaxPeriod(void* encoder_pointer, double maxPeriod,
|
||||
int32_t* status) {
|
||||
Encoder* encoder = (Encoder*)encoder_pointer;
|
||||
encoder->encoder->writeTimerConfig_StallPeriod(
|
||||
(uint32_t)(maxPeriod * 4.0e8 * DECODING_SCALING_FACTOR), status);
|
||||
void Encoder::SetupCounter(uint8_t port_a_module, uint32_t port_a_pin,
|
||||
bool port_a_analog_trigger, uint8_t port_b_module,
|
||||
uint32_t port_b_pin, bool port_b_analog_trigger,
|
||||
bool reverseDirection,
|
||||
EncoderEncodingType encodingType, int32_t* status) {
|
||||
m_encodingScale = encodingType == HAL_Encoder_k1X ? 1 : 2;
|
||||
m_counter = initializeCounter(kExternalDirection, &m_index, status);
|
||||
if (*status != 0) return;
|
||||
setCounterMaxPeriod(m_counter, 0.5, status);
|
||||
if (*status != 0) return;
|
||||
setCounterUpSource(m_counter, port_a_pin, port_a_analog_trigger, status);
|
||||
if (*status != 0) return;
|
||||
setCounterDownSource(m_counter, port_b_pin, port_b_analog_trigger, status);
|
||||
if (*status != 0) return;
|
||||
if (encodingType == HAL_Encoder_k1X) {
|
||||
setCounterUpSourceEdge(m_counter, true, false, status);
|
||||
setCounterAverageSize(m_counter, 1, status);
|
||||
} else {
|
||||
setCounterUpSourceEdge(m_counter, true, true, status);
|
||||
setCounterAverageSize(m_counter, 2, status);
|
||||
}
|
||||
setCounterDownSourceEdge(m_counter, reverseDirection, true, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the encoder is stopped.
|
||||
* Using the MaxPeriod value, a boolean is returned that is true if the encoder
|
||||
* is considered stopped and false if it is still moving. A stopped encoder is
|
||||
* one where the most recent pulse width exceeds the MaxPeriod.
|
||||
* @return True if the encoder is considered stopped.
|
||||
*/
|
||||
bool getEncoderStopped(void* encoder_pointer, int32_t* status) {
|
||||
Encoder* encoder = (Encoder*)encoder_pointer;
|
||||
return encoder->encoder->readTimerOutput_Stalled(status) != 0;
|
||||
Encoder::~Encoder() {
|
||||
if (m_counter != HAL_INVALID_HANDLE) {
|
||||
int32_t status = 0;
|
||||
freeCounter(m_counter, &status);
|
||||
} else {
|
||||
int32_t status = 0;
|
||||
freeFPGAEncoder(m_encoder, &status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The last direction the encoder value changed.
|
||||
* @return The last direction the encoder value changed.
|
||||
*/
|
||||
bool getEncoderDirection(void* encoder_pointer, int32_t* status) {
|
||||
Encoder* encoder = (Encoder*)encoder_pointer;
|
||||
return encoder->encoder->readOutput_Direction(status);
|
||||
// CounterBase interface
|
||||
int32_t Encoder::Get(int32_t* status) const {
|
||||
return (int32_t)(GetRaw(status) * DecodingScaleFactor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the direction sensing for this encoder.
|
||||
* This sets the direction sensing on the encoder so that it could count in the
|
||||
* correct software direction regardless of the mounting.
|
||||
* @param reverseDirection true if the encoder direction should be reversed
|
||||
*/
|
||||
void setEncoderReverseDirection(void* encoder_pointer, bool reverseDirection,
|
||||
int32_t* status) {
|
||||
Encoder* encoder = (Encoder*)encoder_pointer;
|
||||
encoder->encoder->writeConfig_Reverse(reverseDirection, status);
|
||||
int32_t Encoder::GetRaw(int32_t* status) const {
|
||||
if (m_counter) {
|
||||
return getCounter(m_counter, status);
|
||||
} else {
|
||||
return getFPGAEncoder(m_encoder, status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Samples to Average which specifies the number of samples of the timer
|
||||
* to average when calculating the period. Perform averaging to account for
|
||||
* mechanical imperfections or as oversampling to increase resolution.
|
||||
* @param samplesToAverage The number of samples to average from 1 to 127.
|
||||
*/
|
||||
void setEncoderSamplesToAverage(void* encoder_pointer,
|
||||
uint32_t samplesToAverage, int32_t* status) {
|
||||
Encoder* encoder = (Encoder*)encoder_pointer;
|
||||
int32_t Encoder::GetEncodingScale(int32_t* status) const {
|
||||
return m_encodingScale;
|
||||
}
|
||||
|
||||
void Encoder::Reset(int32_t* status) {
|
||||
if (m_counter) {
|
||||
resetCounter(m_counter, status);
|
||||
} else {
|
||||
resetFPGAEncoder(m_encoder, status);
|
||||
}
|
||||
}
|
||||
|
||||
double Encoder::GetPeriod(int32_t* status) const {
|
||||
if (m_counter) {
|
||||
return getCounterPeriod(m_counter, status) / DecodingScaleFactor();
|
||||
} else {
|
||||
return getFPGAEncoderPeriod(m_encoder, status);
|
||||
}
|
||||
}
|
||||
|
||||
void Encoder::SetMaxPeriod(double maxPeriod, int32_t* status) {
|
||||
if (m_counter) {
|
||||
setCounterMaxPeriod(m_counter, maxPeriod, status);
|
||||
} else {
|
||||
setFPGAEncoderMaxPeriod(m_encoder, maxPeriod, status);
|
||||
}
|
||||
}
|
||||
|
||||
bool Encoder::GetStopped(int32_t* status) const {
|
||||
if (m_counter) {
|
||||
return getCounterStopped(m_counter, status);
|
||||
} else {
|
||||
return getFPGAEncoderStopped(m_encoder, status);
|
||||
}
|
||||
}
|
||||
|
||||
bool Encoder::GetDirection(int32_t* status) const {
|
||||
if (m_counter) {
|
||||
return getCounterDirection(m_counter, status);
|
||||
} else {
|
||||
return getFPGAEncoderDirection(m_encoder, status);
|
||||
}
|
||||
}
|
||||
|
||||
double Encoder::GetDistance(int32_t* status) const {
|
||||
return GetRaw(status) * DecodingScaleFactor() * m_distancePerPulse;
|
||||
}
|
||||
|
||||
double Encoder::GetRate(int32_t* status) const {
|
||||
return m_distancePerPulse / GetPeriod(status);
|
||||
}
|
||||
|
||||
void Encoder::SetMinRate(double minRate, int32_t* status) {
|
||||
SetMaxPeriod(m_distancePerPulse / minRate, status);
|
||||
}
|
||||
|
||||
void Encoder::SetDistancePerPulse(double distancePerPulse, int32_t* status) {
|
||||
m_distancePerPulse = distancePerPulse;
|
||||
}
|
||||
|
||||
void Encoder::SetReverseDirection(bool reverseDirection, int32_t* status) {
|
||||
if (m_counter) {
|
||||
setCounterReverseDirection(m_counter, reverseDirection, status);
|
||||
} else {
|
||||
setFPGAEncoderReverseDirection(m_encoder, reverseDirection, status);
|
||||
}
|
||||
}
|
||||
|
||||
void Encoder::SetSamplesToAverage(int samplesToAverage, int32_t* status) {
|
||||
if (samplesToAverage < 1 || samplesToAverage > 127) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
if (m_counter) {
|
||||
setCounterSamplesToAverage(m_counter, samplesToAverage, status);
|
||||
} else {
|
||||
setFPGAEncoderSamplesToAverage(m_encoder, samplesToAverage, status);
|
||||
}
|
||||
encoder->encoder->writeTimerConfig_AverageSize(samplesToAverage, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Samples to Average which specifies the number of samples of the timer
|
||||
* to average when calculating the period. Perform averaging to account for
|
||||
* mechanical imperfections or as oversampling to increase resolution.
|
||||
* @return SamplesToAverage The number of samples being averaged (from 1 to 127)
|
||||
*/
|
||||
uint32_t getEncoderSamplesToAverage(void* encoder_pointer, int32_t* status) {
|
||||
Encoder* encoder = (Encoder*)encoder_pointer;
|
||||
return encoder->encoder->readTimerConfig_AverageSize(status);
|
||||
int32_t Encoder::GetSamplesToAverage(int32_t* status) const {
|
||||
if (m_counter) {
|
||||
return getCounterSamplesToAverage(m_counter, status);
|
||||
} else {
|
||||
return getFPGAEncoderSamplesToAverage(m_encoder, status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an index source for an encoder, which is an input that resets the
|
||||
* encoder's count.
|
||||
*/
|
||||
void setEncoderIndexSource(void* encoder_pointer, uint32_t pin,
|
||||
bool analogTrigger, bool activeHigh,
|
||||
bool edgeSensitive, int32_t* status) {
|
||||
Encoder* encoder = (Encoder*)encoder_pointer;
|
||||
encoder->encoder->writeConfig_IndexSource_Channel((unsigned char)pin, status);
|
||||
encoder->encoder->writeConfig_IndexSource_Module((unsigned char)0, status);
|
||||
encoder->encoder->writeConfig_IndexSource_AnalogTrigger(analogTrigger,
|
||||
status);
|
||||
encoder->encoder->writeConfig_IndexActiveHigh(activeHigh, status);
|
||||
encoder->encoder->writeConfig_IndexEdgeSensitive(edgeSensitive, status);
|
||||
void Encoder::SetIndexSource(uint32_t pin, bool analogTrigger,
|
||||
EncoderIndexingType type, int32_t* status) {
|
||||
if (m_counter) {
|
||||
*status = HAL_COUNTER_NOT_SUPPORTED;
|
||||
return;
|
||||
}
|
||||
bool activeHigh =
|
||||
(type == HAL_kResetWhileHigh) || (type == HAL_kResetOnRisingEdge);
|
||||
bool edgeSensitive =
|
||||
(type == HAL_kResetOnFallingEdge) || (type == HAL_kResetOnRisingEdge);
|
||||
setFPGAEncoderIndexSource(m_encoder, pin, analogTrigger, activeHigh,
|
||||
edgeSensitive, status);
|
||||
}
|
||||
|
||||
double Encoder::DecodingScaleFactor() const {
|
||||
switch (m_encodingType) {
|
||||
case HAL_Encoder_k1X:
|
||||
return 1.0;
|
||||
case HAL_Encoder_k2X:
|
||||
return 0.5;
|
||||
case HAL_Encoder_k4X:
|
||||
return 0.25;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
static LimitedClassedHandleResource<
|
||||
HalEncoderHandle, Encoder, tEncoder::kNumSystems + tCounter::kNumSystems,
|
||||
HalHandleEnum::Encoder>
|
||||
encoderHandles;
|
||||
|
||||
extern "C" {
|
||||
HalEncoderHandle initializeEncoder(
|
||||
uint8_t port_a_module, uint32_t port_a_pin, bool port_a_analog_trigger,
|
||||
uint8_t port_b_module, uint32_t port_b_pin, bool port_b_analog_trigger,
|
||||
bool reverseDirection, EncoderEncodingType encodingType, int32_t* status) {
|
||||
auto encoder = std::make_shared<Encoder>(
|
||||
port_a_module, port_a_pin, port_a_analog_trigger, port_b_module,
|
||||
port_b_pin, port_b_analog_trigger, reverseDirection, encodingType,
|
||||
status);
|
||||
if (*status != 0) return HAL_INVALID_HANDLE; // return in creation error
|
||||
auto handle = encoderHandles.Allocate(encoder);
|
||||
if (handle == HAL_INVALID_HANDLE) {
|
||||
*status = NO_AVAILABLE_RESOURCES;
|
||||
return HAL_INVALID_HANDLE;
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
void freeEncoder(HalEncoderHandle encoder_handle, int32_t* status) {
|
||||
encoderHandles.Free(encoder_handle);
|
||||
}
|
||||
|
||||
int32_t getEncoder(HalEncoderHandle encoder_handle, int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->Get(status);
|
||||
}
|
||||
|
||||
int32_t getEncoderRaw(HalEncoderHandle encoder_handle, int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->GetRaw(status);
|
||||
}
|
||||
|
||||
int32_t getEncoderEncodingScale(HalEncoderHandle encoder_handle,
|
||||
int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->GetEncodingScale(status);
|
||||
}
|
||||
|
||||
void resetEncoder(HalEncoderHandle encoder_handle, int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
encoder->Reset(status);
|
||||
}
|
||||
|
||||
int32_t getEncoderPeriod(HalEncoderHandle encoder_handle, int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->GetPeriod(status);
|
||||
}
|
||||
|
||||
void setEncoderMaxPeriod(HalEncoderHandle encoder_handle, double maxPeriod,
|
||||
int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
encoder->SetMaxPeriod(maxPeriod, status);
|
||||
}
|
||||
|
||||
uint8_t getEncoderStopped(HalEncoderHandle encoder_handle, int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->GetStopped(status);
|
||||
}
|
||||
|
||||
uint8_t getEncoderDirection(HalEncoderHandle encoder_handle, int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->GetDirection(status);
|
||||
}
|
||||
|
||||
double getEncoderDistance(HalEncoderHandle encoder_handle, int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->GetDistance(status);
|
||||
}
|
||||
|
||||
double getEncoderRate(HalEncoderHandle encoder_handle, int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->GetRate(status);
|
||||
}
|
||||
|
||||
void setEncoderMinRate(HalEncoderHandle encoder_handle, double minRate,
|
||||
int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
encoder->SetMinRate(minRate, status);
|
||||
}
|
||||
|
||||
void setEncoderDistancePerPulse(HalEncoderHandle encoder_handle,
|
||||
double distancePerPulse, int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
encoder->SetDistancePerPulse(distancePerPulse, status);
|
||||
}
|
||||
|
||||
void setEncoderReverseDirection(HalEncoderHandle encoder_handle,
|
||||
uint8_t reverseDirection, int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
encoder->SetReverseDirection(reverseDirection, status);
|
||||
}
|
||||
|
||||
void setEncoderSamplesToAverage(HalEncoderHandle encoder_handle,
|
||||
int32_t samplesToAverage, int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
encoder->SetSamplesToAverage(samplesToAverage, status);
|
||||
}
|
||||
|
||||
int32_t getEncoderSamplesToAverage(HalEncoderHandle encoder_handle,
|
||||
int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->GetSamplesToAverage(status);
|
||||
}
|
||||
|
||||
double getEncoderDecodingScaleFactor(HalEncoderHandle encoder_handle,
|
||||
int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->DecodingScaleFactor();
|
||||
}
|
||||
|
||||
double getEncoderDistancePerPulse(HalEncoderHandle encoder_handle,
|
||||
int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->GetDistancePerPulse();
|
||||
}
|
||||
|
||||
EncoderEncodingType getEncoderEncodingType(HalEncoderHandle encoder_handle,
|
||||
int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return HAL_Encoder_k4X; // default to k4X
|
||||
}
|
||||
return encoder->GetEncodingType();
|
||||
}
|
||||
|
||||
void setEncoderIndexSource(HalEncoderHandle encoder_handle, uint32_t pin,
|
||||
uint8_t analogTrigger, EncoderIndexingType type,
|
||||
int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
encoder->SetIndexSource(pin, analogTrigger, type, status);
|
||||
}
|
||||
|
||||
int32_t getEncoderFPGAIndex(HalEncoderHandle encoder_handle, int32_t* status) {
|
||||
auto encoder = encoderHandles.Get(encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->GetFPGAIndex();
|
||||
}
|
||||
}
|
||||
|
||||
74
hal/lib/athena/EncoderInternal.h
Normal file
74
hal/lib/athena/EncoderInternal.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2016. 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "HAL/Encoder.h"
|
||||
|
||||
namespace hal {
|
||||
class Encoder {
|
||||
public:
|
||||
Encoder(uint8_t port_a_module, uint32_t port_a_pin,
|
||||
bool port_a_analog_trigger, uint8_t port_b_module,
|
||||
uint32_t port_b_pin, bool port_b_analog_trigger,
|
||||
bool reverseDirection, EncoderEncodingType encodingType,
|
||||
int32_t* status);
|
||||
~Encoder();
|
||||
|
||||
// CounterBase interface
|
||||
int32_t Get(int32_t* status) const;
|
||||
int32_t GetRaw(int32_t* status) const;
|
||||
int32_t GetEncodingScale(int32_t* status) const;
|
||||
void Reset(int32_t* status);
|
||||
double GetPeriod(int32_t* status) const;
|
||||
void SetMaxPeriod(double maxPeriod, int32_t* status);
|
||||
bool GetStopped(int32_t* status) const;
|
||||
bool GetDirection(int32_t* status) const;
|
||||
|
||||
double GetDistance(int32_t* status) const;
|
||||
double GetRate(int32_t* status) const;
|
||||
void SetMinRate(double minRate, int32_t* status);
|
||||
void SetDistancePerPulse(double distancePerPulse, int32_t* status);
|
||||
void SetReverseDirection(bool reverseDirection, int32_t* status);
|
||||
void SetSamplesToAverage(int samplesToAverage, int32_t* status);
|
||||
int32_t GetSamplesToAverage(int32_t* status) const;
|
||||
|
||||
void SetIndexSource(uint32_t pin, bool analogTrigger,
|
||||
EncoderIndexingType type, int32_t* status);
|
||||
|
||||
int32_t GetFPGAIndex() const { return m_index; }
|
||||
|
||||
int32_t GetEncodingScale() const { return m_encodingScale; }
|
||||
|
||||
double DecodingScaleFactor() const;
|
||||
|
||||
double GetDistancePerPulse() const { return m_distancePerPulse; }
|
||||
|
||||
EncoderEncodingType GetEncodingType() const { return m_encodingType; }
|
||||
|
||||
private:
|
||||
void SetupCounter(uint8_t port_a_module, uint32_t port_a_pin,
|
||||
bool port_a_analog_trigger, uint8_t port_b_module,
|
||||
uint32_t port_b_pin, bool port_b_analog_trigger,
|
||||
bool reverseDirection, EncoderEncodingType encodingType,
|
||||
int32_t* status);
|
||||
|
||||
HalFPGAEncoderHandle m_encoder = HAL_INVALID_HANDLE;
|
||||
|
||||
HalCounterHandle m_counter = HAL_INVALID_HANDLE;
|
||||
|
||||
int32_t m_index = 0;
|
||||
|
||||
double m_distancePerPulse = 1.0;
|
||||
|
||||
EncoderEncodingType m_encodingType;
|
||||
|
||||
int32_t m_encodingScale;
|
||||
};
|
||||
}
|
||||
272
hal/lib/athena/FPGAEncoder.cpp
Normal file
272
hal/lib/athena/FPGAEncoder.cpp
Normal file
@@ -0,0 +1,272 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2016. 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "FPGAEncoder.h"
|
||||
|
||||
#include "DigitalInternal.h"
|
||||
#include "handles/LimitedHandleResource.h"
|
||||
|
||||
static_assert(sizeof(uint32_t) <= sizeof(void*),
|
||||
"This file shoves uint32_ts into pointers.");
|
||||
|
||||
using namespace hal;
|
||||
|
||||
namespace {
|
||||
struct Encoder {
|
||||
tEncoder* encoder;
|
||||
uint32_t index;
|
||||
};
|
||||
}
|
||||
|
||||
static const double DECODING_SCALING_FACTOR = 0.25;
|
||||
|
||||
static LimitedHandleResource<HalFPGAEncoderHandle, Encoder,
|
||||
tEncoder::kNumSystems, HalHandleEnum::FPGAEncoder>
|
||||
fpgaEncoderHandles;
|
||||
|
||||
extern "C" {
|
||||
HalFPGAEncoderHandle initializeFPGAEncoder(
|
||||
uint8_t port_a_module, uint32_t port_a_pin, bool port_a_analog_trigger,
|
||||
uint8_t port_b_module, uint32_t port_b_pin, bool port_b_analog_trigger,
|
||||
bool reverseDirection, int32_t* index, int32_t* status) {
|
||||
remapDigitalSource(port_a_analog_trigger, port_a_pin, port_a_module);
|
||||
remapDigitalSource(port_b_analog_trigger, port_b_pin, port_b_module);
|
||||
|
||||
auto handle = fpgaEncoderHandles.Allocate();
|
||||
if (handle == HAL_INVALID_HANDLE) { // out of resources
|
||||
*status = NO_AVAILABLE_RESOURCES;
|
||||
return HAL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
auto encoder = fpgaEncoderHandles.Get(handle);
|
||||
if (encoder == nullptr) { // will only error on thread issue
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return HAL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
encoder->index = static_cast<uint32_t>(getHandleIndex(handle));
|
||||
|
||||
*index = encoder->index;
|
||||
// TODO: if (index == ~0ul) { CloneError(quadEncoders); return; }
|
||||
encoder->encoder = tEncoder::create(encoder->index, status);
|
||||
encoder->encoder->writeConfig_ASource_Module(port_a_module, status);
|
||||
encoder->encoder->writeConfig_ASource_Channel(port_a_pin, status);
|
||||
encoder->encoder->writeConfig_ASource_AnalogTrigger(port_a_analog_trigger,
|
||||
status);
|
||||
encoder->encoder->writeConfig_BSource_Module(port_b_module, status);
|
||||
encoder->encoder->writeConfig_BSource_Channel(port_b_pin, status);
|
||||
encoder->encoder->writeConfig_BSource_AnalogTrigger(port_b_analog_trigger,
|
||||
status);
|
||||
encoder->encoder->strobeReset(status);
|
||||
encoder->encoder->writeConfig_Reverse(reverseDirection, status);
|
||||
encoder->encoder->writeTimerConfig_AverageSize(4, status);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void freeFPGAEncoder(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
int32_t* status) {
|
||||
auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle);
|
||||
fpgaEncoderHandles.Free(fpga_encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
delete encoder->encoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the Encoder distance to zero.
|
||||
* Resets the current count to zero on the encoder.
|
||||
*/
|
||||
void resetFPGAEncoder(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
int32_t* status) {
|
||||
auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
encoder->encoder->strobeReset(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fpga value from the encoder.
|
||||
* The fpga value is the actual count unscaled by the 1x, 2x, or 4x scale
|
||||
* factor.
|
||||
* @return Current fpga count from the encoder
|
||||
*/
|
||||
int32_t getFPGAEncoder(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
int32_t* status) {
|
||||
auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->encoder->readOutput_Value(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the period of the most recent pulse.
|
||||
* Returns the period of the most recent Encoder pulse in seconds.
|
||||
* This method compenstates for the decoding type.
|
||||
*
|
||||
* @deprecated Use GetRate() in favor of this method. This returns unscaled
|
||||
* periods and GetRate() scales using value from SetDistancePerPulse().
|
||||
*
|
||||
* @return Period in seconds of the most recent pulse.
|
||||
*/
|
||||
double getFPGAEncoderPeriod(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
int32_t* status) {
|
||||
auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0.0;
|
||||
}
|
||||
tEncoder::tTimerOutput output = encoder->encoder->readTimerOutput(status);
|
||||
double value;
|
||||
if (output.Stalled) {
|
||||
// Return infinity
|
||||
double zero = 0.0;
|
||||
value = 1.0 / zero;
|
||||
} else {
|
||||
// output.Period is a fixed point number that counts by 2 (24 bits, 25
|
||||
// integer bits)
|
||||
value = (double)(output.Period << 1) / (double)output.Count;
|
||||
}
|
||||
double measuredPeriod = value * 2.5e-8;
|
||||
return measuredPeriod / DECODING_SCALING_FACTOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum period for stopped detection.
|
||||
* Sets the value that represents the maximum period of the Encoder before it
|
||||
* will assume that the attached device is stopped. This timeout allows users
|
||||
* to determine if the wheels or other shaft has stopped rotating.
|
||||
* This method compensates for the decoding type.
|
||||
*
|
||||
* @deprecated Use SetMinRate() in favor of this method. This takes unscaled
|
||||
* periods and SetMinRate() scales using value from SetDistancePerPulse().
|
||||
*
|
||||
* @param maxPeriod The maximum time between rising and falling edges before the
|
||||
* FPGA will
|
||||
* report the device stopped. This is expressed in seconds.
|
||||
*/
|
||||
void setFPGAEncoderMaxPeriod(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
double maxPeriod, int32_t* status) {
|
||||
auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
encoder->encoder->writeTimerConfig_StallPeriod(
|
||||
(uint32_t)(maxPeriod * 4.0e8 * DECODING_SCALING_FACTOR), status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the encoder is stopped.
|
||||
* Using the MaxPeriod value, a boolean is returned that is true if the encoder
|
||||
* is considered stopped and false if it is still moving. A stopped encoder is
|
||||
* one where the most recent pulse width exceeds the MaxPeriod.
|
||||
* @return True if the encoder is considered stopped.
|
||||
*/
|
||||
bool getFPGAEncoderStopped(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
int32_t* status) {
|
||||
auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return false;
|
||||
}
|
||||
return encoder->encoder->readTimerOutput_Stalled(status) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The last direction the encoder value changed.
|
||||
* @return The last direction the encoder value changed.
|
||||
*/
|
||||
bool getFPGAEncoderDirection(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
int32_t* status) {
|
||||
auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return false;
|
||||
}
|
||||
return encoder->encoder->readOutput_Direction(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the direction sensing for this encoder.
|
||||
* This sets the direction sensing on the encoder so that it could count in the
|
||||
* correct software direction regardless of the mounting.
|
||||
* @param reverseDirection true if the encoder direction should be reversed
|
||||
*/
|
||||
void setFPGAEncoderReverseDirection(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
bool reverseDirection, int32_t* status) {
|
||||
auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
encoder->encoder->writeConfig_Reverse(reverseDirection, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Samples to Average which specifies the number of samples of the timer
|
||||
* to average when calculating the period. Perform averaging to account for
|
||||
* mechanical imperfections or as oversampling to increase resolution.
|
||||
* @param samplesToAverage The number of samples to average from 1 to 127.
|
||||
*/
|
||||
void setFPGAEncoderSamplesToAverage(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
uint32_t samplesToAverage,
|
||||
int32_t* status) {
|
||||
auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
if (samplesToAverage < 1 || samplesToAverage > 127) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
}
|
||||
encoder->encoder->writeTimerConfig_AverageSize(samplesToAverage, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Samples to Average which specifies the number of samples of the timer
|
||||
* to average when calculating the period. Perform averaging to account for
|
||||
* mechanical imperfections or as oversampling to increase resolution.
|
||||
* @return SamplesToAverage The number of samples being averaged (from 1 to 127)
|
||||
*/
|
||||
uint32_t getFPGAEncoderSamplesToAverage(
|
||||
HalFPGAEncoderHandle fpga_encoder_handle, int32_t* status) {
|
||||
auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
return encoder->encoder->readTimerConfig_AverageSize(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an index source for an encoder, which is an input that resets the
|
||||
* encoder's count.
|
||||
*/
|
||||
void setFPGAEncoderIndexSource(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
uint32_t pin, bool analogTrigger,
|
||||
bool activeHigh, bool edgeSensitive,
|
||||
int32_t* status) {
|
||||
auto encoder = fpgaEncoderHandles.Get(fpga_encoder_handle);
|
||||
if (encoder == nullptr) {
|
||||
*status = PARAMETER_OUT_OF_RANGE;
|
||||
return;
|
||||
}
|
||||
encoder->encoder->writeConfig_IndexSource_Channel((unsigned char)pin, status);
|
||||
encoder->encoder->writeConfig_IndexSource_Module((unsigned char)0, status);
|
||||
encoder->encoder->writeConfig_IndexSource_AnalogTrigger(analogTrigger,
|
||||
status);
|
||||
encoder->encoder->writeConfig_IndexActiveHigh(activeHigh, status);
|
||||
encoder->encoder->writeConfig_IndexEdgeSensitive(edgeSensitive, status);
|
||||
}
|
||||
}
|
||||
43
hal/lib/athena/FPGAEncoder.h
Normal file
43
hal/lib/athena/FPGAEncoder.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2016. 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "HAL/Handles.h"
|
||||
|
||||
extern "C" {
|
||||
HalFPGAEncoderHandle initializeFPGAEncoder(
|
||||
uint8_t port_a_module, uint32_t port_a_pin, bool port_a_analog_trigger,
|
||||
uint8_t port_b_module, uint32_t port_b_pin, bool port_b_analog_trigger,
|
||||
bool reverseDirection, int32_t* index,
|
||||
int32_t* status); // TODO: fix routing
|
||||
void freeFPGAEncoder(HalFPGAEncoderHandle fpga_encoder_handle, int32_t* status);
|
||||
void resetFPGAEncoder(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
int32_t* status);
|
||||
int32_t getFPGAEncoder(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
int32_t* status); // Raw value
|
||||
double getFPGAEncoderPeriod(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
int32_t* status);
|
||||
void setFPGAEncoderMaxPeriod(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
double maxPeriod, int32_t* status);
|
||||
bool getFPGAEncoderStopped(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
int32_t* status);
|
||||
bool getFPGAEncoderDirection(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
int32_t* status);
|
||||
void setFPGAEncoderReverseDirection(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
bool reverseDirection, int32_t* status);
|
||||
void setFPGAEncoderSamplesToAverage(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
uint32_t samplesToAverage, int32_t* status);
|
||||
uint32_t getFPGAEncoderSamplesToAverage(
|
||||
HalFPGAEncoderHandle fpga_encoder_handle, int32_t* status);
|
||||
void setFPGAEncoderIndexSource(HalFPGAEncoderHandle fpga_encoder_handle,
|
||||
uint32_t pin, bool analogTrigger,
|
||||
bool activeHigh, bool edgeSensitive,
|
||||
int32_t* status);
|
||||
}
|
||||
@@ -111,6 +111,8 @@ const char* getHALErrorMessage(int32_t code) {
|
||||
return ANALOG_TRIGGER_PULSE_OUTPUT_ERROR_MESSAGE;
|
||||
case PARAMETER_OUT_OF_RANGE:
|
||||
return PARAMETER_OUT_OF_RANGE_MESSAGE;
|
||||
case HAL_COUNTER_NOT_SUPPORTED:
|
||||
return HAL_COUNTER_NOT_SUPPORTED_MESSAGE;
|
||||
case ERR_CANSessionMux_InvalidBuffer:
|
||||
return ERR_CANSessionMux_InvalidBuffer_MESSAGE;
|
||||
case ERR_CANSessionMux_MessageNotFound:
|
||||
|
||||
@@ -38,6 +38,8 @@ enum class HalHandleEnum {
|
||||
PWM = 9,
|
||||
DigitalPWM = 10,
|
||||
Counter = 11,
|
||||
FPGAEncoder = 12,
|
||||
Encoder = 13,
|
||||
Compressor = 14,
|
||||
Solenoid = 15
|
||||
};
|
||||
|
||||
99
hal/lib/athena/handles/LimitedClassedHandleResource.h
Normal file
99
hal/lib/athena/handles/LimitedClassedHandleResource.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2016. 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "HAL/Handles.h"
|
||||
#include "HAL/cpp/priority_mutex.h"
|
||||
#include "HandlesInternal.h"
|
||||
|
||||
namespace hal {
|
||||
|
||||
/**
|
||||
* The LimitedClassedHandleResource class is a way to track handles. This
|
||||
* version
|
||||
* allows a limited number of handles that are allocated sequentially.
|
||||
*
|
||||
* @tparam THandle The Handle Type (Must be typedefed from HalHandle)
|
||||
* @tparam TStruct The struct type held by this resource
|
||||
* @tparam size The number of resources allowed to be allocated
|
||||
* @tparam enumValue The type value stored in the handle
|
||||
*
|
||||
*/
|
||||
template <typename THandle, typename TStruct, int16_t size,
|
||||
HalHandleEnum enumValue>
|
||||
class LimitedClassedHandleResource {
|
||||
friend class LimitedClassedHandleResourceTest;
|
||||
|
||||
public:
|
||||
LimitedClassedHandleResource(const LimitedClassedHandleResource&) = delete;
|
||||
LimitedClassedHandleResource operator=(const LimitedClassedHandleResource&) =
|
||||
delete;
|
||||
LimitedClassedHandleResource() = default;
|
||||
THandle Allocate(std::shared_ptr<TStruct> toSet);
|
||||
std::shared_ptr<TStruct> Get(THandle handle);
|
||||
void Free(THandle handle);
|
||||
|
||||
private:
|
||||
std::shared_ptr<TStruct> m_structures[size];
|
||||
priority_mutex m_handleMutexes[size];
|
||||
priority_mutex m_allocateMutex;
|
||||
};
|
||||
|
||||
template <typename THandle, typename TStruct, int16_t size,
|
||||
HalHandleEnum enumValue>
|
||||
THandle
|
||||
LimitedClassedHandleResource<THandle, TStruct, size, enumValue>::Allocate(
|
||||
std::shared_ptr<TStruct> toSet) {
|
||||
// globally lock to loop through indices
|
||||
std::lock_guard<priority_mutex> sync(m_allocateMutex);
|
||||
int16_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
if (m_structures[i] == nullptr) {
|
||||
// if a false index is found, grab its specific mutex
|
||||
// and allocate it.
|
||||
std::lock_guard<priority_mutex> sync(m_handleMutexes[i]);
|
||||
m_structures[i] = toSet;
|
||||
return (THandle)createHandle(i, enumValue);
|
||||
}
|
||||
}
|
||||
return HAL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
template <typename THandle, typename TStruct, int16_t size,
|
||||
HalHandleEnum enumValue>
|
||||
std::shared_ptr<TStruct> LimitedClassedHandleResource<
|
||||
THandle, TStruct, size, enumValue>::Get(THandle handle) {
|
||||
// get handle index, and fail early if index out of range or wrong handle
|
||||
int16_t index = getHandleTypedIndex(handle, enumValue);
|
||||
if (index < 0 || index >= size) {
|
||||
return nullptr;
|
||||
}
|
||||
std::lock_guard<priority_mutex> sync(m_handleMutexes[index]);
|
||||
// return structure. Null will propogate correctly, so no need to manually
|
||||
// check.
|
||||
return m_structures[index];
|
||||
}
|
||||
|
||||
template <typename THandle, typename TStruct, int16_t size,
|
||||
HalHandleEnum enumValue>
|
||||
void LimitedClassedHandleResource<THandle, TStruct, size, enumValue>::Free(
|
||||
THandle handle) {
|
||||
// get handle index, and fail early if index out of range or wrong handle
|
||||
int16_t index = getHandleTypedIndex(handle, enumValue);
|
||||
if (index < 0 || index >= size) return;
|
||||
// lock and deallocated handle
|
||||
std::lock_guard<priority_mutex> sync(m_allocateMutex);
|
||||
std::lock_guard<priority_mutex> lock(m_handleMutexes[index]);
|
||||
m_structures[index].reset();
|
||||
}
|
||||
}
|
||||
@@ -83,7 +83,7 @@ class Counter : public SensorBase,
|
||||
|
||||
void SetSamplesToAverage(int samplesToAverage);
|
||||
int GetSamplesToAverage() const;
|
||||
uint32_t GetFPGAIndex() const { return m_index; }
|
||||
int32_t GetFPGAIndex() const { return m_index; }
|
||||
|
||||
void UpdateTable() override;
|
||||
void StartLiveWindowMode() override;
|
||||
@@ -101,7 +101,7 @@ class Counter : public SensorBase,
|
||||
HalCounterHandle m_counter = HAL_INVALID_HANDLE;
|
||||
|
||||
private:
|
||||
uint32_t m_index = 0; // The index of this counter.
|
||||
int32_t m_index = 0; ///< The index of this counter.
|
||||
|
||||
std::shared_ptr<ITable> m_table;
|
||||
friend class DigitalGlitchFilter;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "Counter.h"
|
||||
#include "CounterBase.h"
|
||||
#include "HAL/Encoder.h"
|
||||
#include "LiveWindow/LiveWindowSendable.h"
|
||||
#include "PIDSource.h"
|
||||
#include "SensorBase.h"
|
||||
@@ -88,21 +89,16 @@ class Encoder : public SensorBase,
|
||||
void InitTable(std::shared_ptr<ITable> subTable) override;
|
||||
std::shared_ptr<ITable> GetTable() const override;
|
||||
|
||||
int32_t GetFPGAIndex() const { return m_index; }
|
||||
int32_t GetFPGAIndex() const;
|
||||
|
||||
private:
|
||||
void InitEncoder(bool _reverseDirection, EncodingType encodingType);
|
||||
void InitEncoder(bool reverseDirection, EncodingType encodingType);
|
||||
|
||||
double DecodingScaleFactor() const;
|
||||
|
||||
std::shared_ptr<DigitalSource> m_aSource; // the A phase of the quad encoder
|
||||
std::shared_ptr<DigitalSource> m_bSource; // the B phase of the quad encoder
|
||||
void* m_encoder = nullptr;
|
||||
int32_t m_index = 0; // The encoder's FPGA index.
|
||||
double m_distancePerPulse = 1.0; // distance of travel for each encoder tick
|
||||
std::unique_ptr<Counter> m_counter =
|
||||
nullptr; // Counter object for 1x and 2x encoding
|
||||
EncodingType m_encodingType; // Encoding type
|
||||
int32_t m_encodingScale; // 1x, 2x, or 4x, per the encodingType
|
||||
HalEncoderHandle m_encoder = HAL_INVALID_HANDLE;
|
||||
|
||||
std::shared_ptr<ITable> m_table;
|
||||
friend class DigitalGlitchFilter;
|
||||
|
||||
@@ -31,44 +31,17 @@
|
||||
* be double (2x) the spec'd count.
|
||||
*/
|
||||
void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType) {
|
||||
m_encodingType = encodingType;
|
||||
switch (encodingType) {
|
||||
case k4X: {
|
||||
m_encodingScale = 4;
|
||||
if (m_aSource->StatusIsFatal()) {
|
||||
CloneError(*m_aSource);
|
||||
return;
|
||||
}
|
||||
if (m_bSource->StatusIsFatal()) {
|
||||
CloneError(*m_bSource);
|
||||
return;
|
||||
}
|
||||
int32_t status = 0;
|
||||
m_encoder = initializeEncoder(
|
||||
m_aSource->GetModuleForRouting(), m_aSource->GetChannelForRouting(),
|
||||
m_aSource->GetAnalogTriggerForRouting(),
|
||||
m_bSource->GetModuleForRouting(), m_bSource->GetChannelForRouting(),
|
||||
m_bSource->GetAnalogTriggerForRouting(), reverseDirection, &m_index,
|
||||
&status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
m_counter = nullptr;
|
||||
SetMaxPeriod(.5);
|
||||
break;
|
||||
}
|
||||
case k1X:
|
||||
case k2X: {
|
||||
m_encodingScale = encodingType == k1X ? 1 : 2;
|
||||
m_counter = std::make_unique<Counter>(m_encodingType, m_aSource,
|
||||
m_bSource, reverseDirection);
|
||||
m_index = m_counter->GetFPGAIndex();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
wpi_setErrorWithContext(-1, "Invalid encodingType argument");
|
||||
break;
|
||||
}
|
||||
int32_t status = 0;
|
||||
m_encoder = initializeEncoder(
|
||||
m_aSource->GetModuleForRouting(), m_aSource->GetChannelForRouting(),
|
||||
m_aSource->GetAnalogTriggerForRouting(), m_bSource->GetModuleForRouting(),
|
||||
m_bSource->GetChannelForRouting(),
|
||||
m_bSource->GetAnalogTriggerForRouting(), reverseDirection,
|
||||
(EncoderEncodingType)encodingType, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
|
||||
HALReport(HALUsageReporting::kResourceType_Encoder, m_index, encodingType);
|
||||
HALReport(HALUsageReporting::kResourceType_Encoder, GetFPGAIndex(),
|
||||
encodingType);
|
||||
LiveWindow::GetInstance()->AddSensor("Encoder",
|
||||
m_aSource->GetChannelForRouting(), this);
|
||||
}
|
||||
@@ -182,11 +155,9 @@ Encoder::Encoder(DigitalSource& aSource, DigitalSource& bSource,
|
||||
* Frees the FPGA resources associated with an Encoder.
|
||||
*/
|
||||
Encoder::~Encoder() {
|
||||
if (!m_counter) {
|
||||
int32_t status = 0;
|
||||
freeEncoder(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
int32_t status = 0;
|
||||
freeEncoder(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,7 +165,12 @@ Encoder::~Encoder() {
|
||||
*
|
||||
* Used to divide raw edge counts down to spec'd counts.
|
||||
*/
|
||||
int32_t Encoder::GetEncodingScale() const { return m_encodingScale; }
|
||||
int32_t Encoder::GetEncodingScale() const {
|
||||
int32_t status = 0;
|
||||
int32_t val = getEncoderEncodingScale(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw value from the encoder.
|
||||
@@ -206,14 +182,9 @@ int32_t Encoder::GetEncodingScale() const { return m_encodingScale; }
|
||||
*/
|
||||
int32_t Encoder::GetRaw() const {
|
||||
if (StatusIsFatal()) return 0;
|
||||
int32_t value;
|
||||
if (m_counter)
|
||||
value = m_counter->Get();
|
||||
else {
|
||||
int32_t status = 0;
|
||||
value = getEncoder(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
int32_t status = 0;
|
||||
int32_t value = getEncoderRaw(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -228,7 +199,10 @@ int32_t Encoder::GetRaw() const {
|
||||
*/
|
||||
int32_t Encoder::Get() const {
|
||||
if (StatusIsFatal()) return 0;
|
||||
return (int32_t)(GetRaw() * DecodingScaleFactor());
|
||||
int32_t status = 0;
|
||||
int32_t value = getEncoder(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,13 +212,10 @@ int32_t Encoder::Get() const {
|
||||
*/
|
||||
void Encoder::Reset() {
|
||||
if (StatusIsFatal()) return;
|
||||
if (m_counter)
|
||||
m_counter->Reset();
|
||||
else {
|
||||
int32_t status = 0;
|
||||
resetEncoder(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
int32_t status = 0;
|
||||
resetEncoder(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,14 +232,10 @@ void Encoder::Reset() {
|
||||
*/
|
||||
double Encoder::GetPeriod() const {
|
||||
if (StatusIsFatal()) return 0.0;
|
||||
if (m_counter) {
|
||||
return m_counter->GetPeriod() / DecodingScaleFactor();
|
||||
} else {
|
||||
int32_t status = 0;
|
||||
double period = getEncoderPeriod(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return period;
|
||||
}
|
||||
int32_t status = 0;
|
||||
double value = getEncoderPeriod(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,13 +256,9 @@ double Encoder::GetPeriod() const {
|
||||
*/
|
||||
void Encoder::SetMaxPeriod(double maxPeriod) {
|
||||
if (StatusIsFatal()) return;
|
||||
if (m_counter) {
|
||||
m_counter->SetMaxPeriod(maxPeriod * DecodingScaleFactor());
|
||||
} else {
|
||||
int32_t status = 0;
|
||||
setEncoderMaxPeriod(m_encoder, maxPeriod, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
int32_t status = 0;
|
||||
setEncoderMaxPeriod(m_encoder, maxPeriod, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,14 +272,10 @@ void Encoder::SetMaxPeriod(double maxPeriod) {
|
||||
*/
|
||||
bool Encoder::GetStopped() const {
|
||||
if (StatusIsFatal()) return true;
|
||||
if (m_counter) {
|
||||
return m_counter->GetStopped();
|
||||
} else {
|
||||
int32_t status = 0;
|
||||
bool value = getEncoderStopped(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return value;
|
||||
}
|
||||
int32_t status = 0;
|
||||
bool value = getEncoderStopped(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -326,14 +285,10 @@ bool Encoder::GetStopped() const {
|
||||
*/
|
||||
bool Encoder::GetDirection() const {
|
||||
if (StatusIsFatal()) return false;
|
||||
if (m_counter) {
|
||||
return m_counter->GetDirection();
|
||||
} else {
|
||||
int32_t status = 0;
|
||||
bool value = getEncoderDirection(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return value;
|
||||
}
|
||||
int32_t status = 0;
|
||||
bool value = getEncoderDirection(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,16 +297,10 @@ bool Encoder::GetDirection() const {
|
||||
*/
|
||||
double Encoder::DecodingScaleFactor() const {
|
||||
if (StatusIsFatal()) return 0.0;
|
||||
switch (m_encodingType) {
|
||||
case k1X:
|
||||
return 1.0;
|
||||
case k2X:
|
||||
return 0.5;
|
||||
case k4X:
|
||||
return 0.25;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
int32_t status = 0;
|
||||
double val = getEncoderDecodingScaleFactor(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -362,7 +311,10 @@ double Encoder::DecodingScaleFactor() const {
|
||||
*/
|
||||
double Encoder::GetDistance() const {
|
||||
if (StatusIsFatal()) return 0.0;
|
||||
return GetRaw() * DecodingScaleFactor() * m_distancePerPulse;
|
||||
int32_t status = 0;
|
||||
double value = getEncoderDistance(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -375,7 +327,10 @@ double Encoder::GetDistance() const {
|
||||
*/
|
||||
double Encoder::GetRate() const {
|
||||
if (StatusIsFatal()) return 0.0;
|
||||
return (m_distancePerPulse / GetPeriod());
|
||||
int32_t status = 0;
|
||||
double value = getEncoderRate(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,7 +341,9 @@ double Encoder::GetRate() const {
|
||||
*/
|
||||
void Encoder::SetMinRate(double minRate) {
|
||||
if (StatusIsFatal()) return;
|
||||
SetMaxPeriod(m_distancePerPulse / minRate);
|
||||
int32_t status = 0;
|
||||
setEncoderMinRate(m_encoder, minRate, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -408,7 +365,9 @@ void Encoder::SetMinRate(double minRate) {
|
||||
*/
|
||||
void Encoder::SetDistancePerPulse(double distancePerPulse) {
|
||||
if (StatusIsFatal()) return;
|
||||
m_distancePerPulse = distancePerPulse;
|
||||
int32_t status = 0;
|
||||
setEncoderDistancePerPulse(m_encoder, distancePerPulse, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -421,13 +380,9 @@ void Encoder::SetDistancePerPulse(double distancePerPulse) {
|
||||
*/
|
||||
void Encoder::SetReverseDirection(bool reverseDirection) {
|
||||
if (StatusIsFatal()) return;
|
||||
if (m_counter) {
|
||||
m_counter->SetReverseDirection(reverseDirection);
|
||||
} else {
|
||||
int32_t status = 0;
|
||||
setEncoderReverseDirection(m_encoder, reverseDirection, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
int32_t status = 0;
|
||||
setEncoderReverseDirection(m_encoder, reverseDirection, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -444,18 +399,11 @@ void Encoder::SetSamplesToAverage(int samplesToAverage) {
|
||||
wpi_setWPIErrorWithContext(
|
||||
ParameterOutOfRange,
|
||||
"Average counter values must be between 1 and 127");
|
||||
return;
|
||||
}
|
||||
int32_t status = 0;
|
||||
switch (m_encodingType) {
|
||||
case k4X:
|
||||
setEncoderSamplesToAverage(m_encoder, samplesToAverage, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
break;
|
||||
case k1X:
|
||||
case k2X:
|
||||
m_counter->SetSamplesToAverage(samplesToAverage);
|
||||
break;
|
||||
}
|
||||
setEncoderSamplesToAverage(m_encoder, samplesToAverage, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -468,18 +416,9 @@ void Encoder::SetSamplesToAverage(int samplesToAverage) {
|
||||
* @return The number of samples being averaged (from 1 to 127)
|
||||
*/
|
||||
int Encoder::GetSamplesToAverage() const {
|
||||
int result = 1;
|
||||
int32_t status = 0;
|
||||
switch (m_encodingType) {
|
||||
case k4X:
|
||||
result = getEncoderSamplesToAverage(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
break;
|
||||
case k1X:
|
||||
case k2X:
|
||||
result = m_counter->GetSamplesToAverage();
|
||||
break;
|
||||
}
|
||||
int result = getEncoderSamplesToAverage(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -510,13 +449,9 @@ double Encoder::PIDGet() {
|
||||
*/
|
||||
void Encoder::SetIndexSource(uint32_t channel, Encoder::IndexingType type) {
|
||||
int32_t status = 0;
|
||||
bool activeHigh = (type == kResetWhileHigh) || (type == kResetOnRisingEdge);
|
||||
bool edgeSensitive =
|
||||
(type == kResetOnFallingEdge) || (type == kResetOnRisingEdge);
|
||||
|
||||
setEncoderIndexSource(m_encoder, channel, false, activeHigh, edgeSensitive,
|
||||
setEncoderIndexSource(m_encoder, channel, false, (EncoderIndexingType)type,
|
||||
&status);
|
||||
wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -544,21 +479,27 @@ void Encoder::SetIndexSource(DigitalSource* source,
|
||||
void Encoder::SetIndexSource(const DigitalSource& source,
|
||||
Encoder::IndexingType type) {
|
||||
int32_t status = 0;
|
||||
bool activeHigh = (type == kResetWhileHigh) || (type == kResetOnRisingEdge);
|
||||
bool edgeSensitive =
|
||||
(type == kResetOnFallingEdge) || (type == kResetOnRisingEdge);
|
||||
|
||||
setEncoderIndexSource(m_encoder, source.GetChannelForRouting(),
|
||||
source.GetAnalogTriggerForRouting(), activeHigh,
|
||||
edgeSensitive, &status);
|
||||
wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
|
||||
source.GetAnalogTriggerForRouting(),
|
||||
(EncoderIndexingType)type, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
}
|
||||
|
||||
int32_t Encoder::GetFPGAIndex() const {
|
||||
int32_t status = 0;
|
||||
int32_t val = getEncoderFPGAIndex(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
return val;
|
||||
}
|
||||
|
||||
void Encoder::UpdateTable() {
|
||||
if (m_table != nullptr) {
|
||||
m_table->PutNumber("Speed", GetRate());
|
||||
m_table->PutNumber("Distance", GetDistance());
|
||||
m_table->PutNumber("Distance per Tick", m_distancePerPulse);
|
||||
int32_t status = 0;
|
||||
double distancePerPulse = getEncoderDistancePerPulse(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
m_table->PutNumber("Distance per Tick", distancePerPulse);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,7 +508,10 @@ void Encoder::StartLiveWindowMode() {}
|
||||
void Encoder::StopLiveWindowMode() {}
|
||||
|
||||
std::string Encoder::GetSmartDashboardType() const {
|
||||
if (m_encodingType == k4X)
|
||||
int32_t status = 0;
|
||||
EncoderEncodingType type = getEncoderEncodingType(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, getHALErrorMessage(status));
|
||||
if (type == EncoderEncodingType::HAL_Encoder_k4X)
|
||||
return "Quadrature Encoder";
|
||||
else
|
||||
return "Encoder";
|
||||
|
||||
@@ -37,9 +37,9 @@ Java_edu_wpi_first_wpilibj_hal_CounterJNI_initializeCounter(
|
||||
COUNTERJNI_LOG(logDEBUG) << "Calling COUNTERJNI initializeCounter";
|
||||
COUNTERJNI_LOG(logDEBUG) << "Mode = " << mode;
|
||||
jint* indexPtr = (jint*)env->GetDirectBufferAddress(index);
|
||||
COUNTERJNI_LOG(logDEBUG) << "Index Ptr = " << (uint32_t*)indexPtr;
|
||||
COUNTERJNI_LOG(logDEBUG) << "Index Ptr = " << (int32_t*)indexPtr;
|
||||
int32_t status = 0;
|
||||
auto counter = initializeCounter((Mode)mode, (uint32_t*)indexPtr, &status);
|
||||
auto counter = initializeCounter((Mode)mode, (int32_t*)indexPtr, &status);
|
||||
COUNTERJNI_LOG(logDEBUG) << "Index = " << *indexPtr;
|
||||
COUNTERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
COUNTERJNI_LOG(logDEBUG) << "COUNTER Handle = " << counter;
|
||||
|
||||
@@ -29,13 +29,13 @@ extern "C" {
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: initializeEncoder
|
||||
* Signature: (BIZBIZZLjava/nio/IntBuffer;)J
|
||||
* Signature: (BIZBIZZI)I
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_initializeEncoder(
|
||||
JNIEnv* env, jclass, jbyte port_a_module, jint port_a_pin,
|
||||
jboolean port_a_analog_trigger, jbyte port_b_module, jint port_b_pin,
|
||||
jboolean port_b_analog_trigger, jboolean reverseDirection, jobject index) {
|
||||
jboolean port_b_analog_trigger, jboolean reverseDirection, jint encodingType) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI initializeEncoder";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Module A = " << (jint)port_a_module;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Pin A = " << port_a_pin;
|
||||
@@ -46,46 +46,30 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_initializeEncoder(
|
||||
ENCODERJNI_LOG(logDEBUG) << "Analog Trigger B = "
|
||||
<< (jint)port_b_analog_trigger;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Reverse direction = " << (jint)reverseDirection;
|
||||
jint* indexPtr = (jint*)env->GetDirectBufferAddress(index);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Index Ptr = " << indexPtr;
|
||||
ENCODERJNI_LOG(logDEBUG) << "EncodingType = " << encodingType;
|
||||
int32_t status = 0;
|
||||
void* encoder = initializeEncoder(
|
||||
auto encoder = initializeEncoder(
|
||||
port_a_module, port_a_pin, port_a_analog_trigger, port_b_module,
|
||||
port_b_pin, port_b_analog_trigger, reverseDirection, indexPtr, &status);
|
||||
|
||||
ENCODERJNI_LOG(logDEBUG) << "Index = " << *indexPtr;
|
||||
port_b_pin, port_b_analog_trigger, reverseDirection,
|
||||
(EncoderEncodingType)encodingType, &status);
|
||||
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "ENCODER Ptr = " << encoder;
|
||||
ENCODERJNI_LOG(logDEBUG) << "ENCODER Handle = " << encoder;
|
||||
CheckStatus(env, status);
|
||||
return (jlong)encoder;
|
||||
return (jint)encoder;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: freeEncoder
|
||||
* Signature: (J)V
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_freeEncoder(
|
||||
JNIEnv* env, jclass, jlong id) {
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI freeEncoder";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
freeEncoder((void*)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: resetEncoder
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_resetEncoder(
|
||||
JNIEnv* env, jclass, jlong id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI resetEncoder";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id;
|
||||
int32_t status = 0;
|
||||
resetEncoder((void*)id, &status);
|
||||
freeEncoder((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
@@ -93,34 +77,83 @@ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_resetEncoder(
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoder
|
||||
* Signature: (J)I
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoder(
|
||||
JNIEnv* env, jclass, jlong id) {
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoder";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jint returnValue = getEncoder((void*)id, &status);
|
||||
jint returnValue = getEncoder((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getEncoderResult = " << returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoderRaw
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderRaw(
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderRaw";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jint returnValue = getEncoderRaw((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getRawEncoderResult = " << returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncodingScaleFactor
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncodingScaleFactor(
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncodingScaleFactor";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jint returnValue = getEncoderEncodingScale((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getEncodingScaleFactorResult = " << returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: resetEncoder
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_EncoderJNI_resetEncoder(
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI resetEncoder";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
resetEncoder((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoderPeriod
|
||||
* Signature: (J)D
|
||||
* Signature: (I)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderPeriod(
|
||||
JNIEnv* env, jclass, jlong id) {
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderPeriod";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
double returnValue = getEncoderPeriod((void*)id, &status);
|
||||
double returnValue = getEncoderPeriod((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getEncoderPeriodResult = " << returnValue;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getEncoderPeriodEncoderResult = " << returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
@@ -128,15 +161,15 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderPeriod(
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: setEncoderMaxPeriod
|
||||
* Signature: (JD)V
|
||||
* Signature: (ID)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderMaxPeriod(
|
||||
JNIEnv* env, jclass, jlong id, jdouble value) {
|
||||
JNIEnv* env, jclass, jint id, jdouble value) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI setEncoderMaxPeriod";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
setEncoderMaxPeriod((void*)id, value, &status);
|
||||
setEncoderMaxPeriod((HalEncoderHandle)id, value, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
@@ -144,17 +177,17 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderMaxPeriod(
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoderStopped
|
||||
* Signature: (J)Z
|
||||
* Signature: (I)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderStopped(
|
||||
JNIEnv* env, jclass, jlong id) {
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderStopped";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jboolean returnValue = getEncoderStopped((void*)id, &status);
|
||||
jboolean returnValue = getEncoderStopped((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getEncoderStoppedResult = " << returnValue;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getStoppedEncoderResult = " << returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
@@ -162,33 +195,101 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderStopped(
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoderDirection
|
||||
* Signature: (J)Z
|
||||
* Signature: (I)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderDirection(
|
||||
JNIEnv* env, jclass, jlong id) {
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderDirection";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jboolean returnValue = getEncoderDirection((void*)id, &status);
|
||||
jboolean returnValue = getEncoderDirection((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getEncoderDirectionResult = " << returnValue;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getDirectionEncoderResult = " << returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoderDistance
|
||||
* Signature: (I)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderDistance(
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderDistance";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jdouble returnValue = getEncoderDistance((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getDistanceEncoderResult = " << returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoderRate
|
||||
* Signature: (I)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderRate(
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderRate";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jdouble returnValue = getEncoderRate((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getRateEncoderResult = " << returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: setEncoderMinRate
|
||||
* Signature: (ID)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderMinRate(
|
||||
JNIEnv* env, jclass, jint id, jdouble value) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI setEncoderMinRate";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
setEncoderMinRate((HalEncoderHandle)id, value, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: setEncoderDistancePerPulse
|
||||
* Signature: (ID)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderDistancePerPulse(
|
||||
JNIEnv* env, jclass, jint id, jdouble value) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI setEncoderDistancePerPulse";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
setEncoderDistancePerPulse((HalEncoderHandle)id, value, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: setEncoderReverseDirection
|
||||
* Signature: (JZ)V
|
||||
* Signature: (IZ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderReverseDirection(
|
||||
JNIEnv* env, jclass, jlong id, jboolean value) {
|
||||
JNIEnv* env, jclass, jint id, jboolean value) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI setEncoderReverseDirection";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
setEncoderReverseDirection((void*)id, value, &status);
|
||||
setEncoderReverseDirection((HalEncoderHandle)id, value, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
@@ -196,15 +297,15 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderReverseDirection(
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: setEncoderSamplesToAverage
|
||||
* Signature: (JI)V
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderSamplesToAverage(
|
||||
JNIEnv* env, jclass, jlong id, jint value) {
|
||||
JNIEnv* env, jclass, jint id, jint value) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI setEncoderSamplesToAverage";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
setEncoderSamplesToAverage((void*)id, value, &status);
|
||||
setEncoderSamplesToAverage((HalEncoderHandle)id, value, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
if (status == PARAMETER_OUT_OF_RANGE) {
|
||||
ThrowBoundaryException(env, value, 1, 127);
|
||||
@@ -216,15 +317,15 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderSamplesToAverage(
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoderSamplesToAverage
|
||||
* Signature: (J)I
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderSamplesToAverage(
|
||||
JNIEnv* env, jclass, jlong id) {
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderSamplesToAverage";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jint returnValue = getEncoderSamplesToAverage((void*)id, &status);
|
||||
jint returnValue = getEncoderSamplesToAverage((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getEncoderSamplesToAverageResult = "
|
||||
<< returnValue;
|
||||
@@ -235,26 +336,118 @@ Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderSamplesToAverage(
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: setEncoderIndexSource
|
||||
* Signature: (JIZZZ)V
|
||||
* Signature: (IIZI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_setEncoderIndexSource(
|
||||
JNIEnv* env, jclass, jlong id, jint pin, jboolean analogTrigger,
|
||||
jboolean activeHigh, jboolean edgeSensitive) {
|
||||
JNIEnv* env, jclass, jint id, jint pin, jboolean analogTrigger,
|
||||
jint type) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI setEncoderIndexSource";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Ptr = " << (void*)id;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Pin = " << pin;
|
||||
ENCODERJNI_LOG(logDEBUG) << "Analog Trigger = "
|
||||
<< (analogTrigger ? "true" : "false");
|
||||
ENCODERJNI_LOG(logDEBUG) << "Active High = "
|
||||
<< (activeHigh ? "true" : "false");
|
||||
ENCODERJNI_LOG(logDEBUG) << "Edge Sensitive = "
|
||||
<< (edgeSensitive ? "true" : "false");
|
||||
ENCODERJNI_LOG(logDEBUG) << "IndexingType = " << type;
|
||||
int32_t status = 0;
|
||||
setEncoderIndexSource((void*)id, pin, analogTrigger, activeHigh,
|
||||
edgeSensitive, &status);
|
||||
setEncoderIndexSource((HalEncoderHandle)id, pin, analogTrigger,
|
||||
(EncoderIndexingType)type, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoderFPGAIndex
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderFPGAIndex(
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderSamplesToAverage";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jint returnValue = getEncoderFPGAIndex((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getEncoderSamplesToAverageResult = "
|
||||
<< returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoderEncodingScale
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderEncodingScale(
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderSamplesToAverage";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jint returnValue = getEncoderEncodingScale((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getEncoderSamplesToAverageResult = "
|
||||
<< returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoderDecodingScaleFactor
|
||||
* Signature: (I)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderDecodingScaleFactor(
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderSamplesToAverage";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jint returnValue = getEncoderDecodingScaleFactor((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getEncoderSamplesToAverageResult = "
|
||||
<< returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoderDistancePerPulse
|
||||
* Signature: (I)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderDistancePerPulse(
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderSamplesToAverage";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jint returnValue = getEncoderDistancePerPulse((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getEncoderSamplesToAverageResult = "
|
||||
<< returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_EncoderJNI
|
||||
* Method: getEncoderEncodingType
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_wpilibj_hal_EncoderJNI_getEncoderEncodingType(
|
||||
JNIEnv* env, jclass, jint id) {
|
||||
ENCODERJNI_LOG(logDEBUG) << "Calling ENCODERJNI getEncoderSamplesToAverage";
|
||||
ENCODERJNI_LOG(logDEBUG) << "Encoder Handle = " << (HalEncoderHandle)id;
|
||||
int32_t status = 0;
|
||||
jint returnValue = getEncoderEncodingType((HalEncoderHandle)id, &status);
|
||||
ENCODERJNI_LOG(logDEBUG) << "Status = " << status;
|
||||
ENCODERJNI_LOG(logDEBUG) << "getEncoderSamplesToAverageResult = "
|
||||
<< returnValue;
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -31,7 +31,14 @@ import edu.wpi.first.wpilibj.tables.ITable;
|
||||
*/
|
||||
public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveWindowSendable {
|
||||
public enum IndexingType {
|
||||
kResetWhileHigh, kResetWhileLow, kResetOnFallingEdge, kResetOnRisingEdge
|
||||
kResetWhileHigh(0), kResetWhileLow(1), kResetOnFallingEdge(2), kResetOnRisingEdge(3);
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
public final int value;
|
||||
|
||||
IndexingType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,24 +55,13 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* The index source.
|
||||
*/
|
||||
protected DigitalSource m_indexSource = null; // Index on some encoders
|
||||
private long m_encoder;
|
||||
private int m_index;
|
||||
private double m_distancePerPulse; // distance of travel for each encoder
|
||||
// tick
|
||||
private Counter m_counter; // Counter object for 1x and 2x encoding
|
||||
/**
|
||||
* Either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If 4X is selected, then an encoder
|
||||
* FPGA object is used and the returned counts will be 4x the encoder spec'd value since all
|
||||
* rising and falling edges are counted. If 1X or 2X are selected then a counter object will be
|
||||
* used and the returned value will either exactly match the spec'd count or be double (2x) the
|
||||
* spec'd count.
|
||||
*/
|
||||
private EncodingType m_encodingType = EncodingType.k4X;
|
||||
private int m_encodingScale; // 1x, 2x, or 4x, per the m_encodingType
|
||||
private boolean m_allocatedA;
|
||||
private boolean m_allocatedB;
|
||||
private boolean m_allocatedI;
|
||||
private PIDSourceType m_pidSource;
|
||||
|
||||
private int m_encoder; // the HAL encoder object
|
||||
|
||||
|
||||
/**
|
||||
* Common initialization code for Encoders. This code allocates resources for Encoders and is
|
||||
@@ -75,36 +71,15 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
*
|
||||
* @param reverseDirection If true, counts down instead of up (this is all relative)
|
||||
*/
|
||||
private void initEncoder(boolean reverseDirection) {
|
||||
switch (m_encodingType) {
|
||||
case k4X:
|
||||
m_encodingScale = 4;
|
||||
ByteBuffer index = ByteBuffer.allocateDirect(4);
|
||||
// set the byte order
|
||||
index.order(ByteOrder.LITTLE_ENDIAN);
|
||||
m_encoder =
|
||||
EncoderJNI.initializeEncoder(m_aSource.getModuleForRouting(), m_aSource
|
||||
.getChannelForRouting(), m_aSource.getAnalogTriggerForRouting(),
|
||||
m_bSource.getModuleForRouting(), m_bSource.getChannelForRouting(),
|
||||
m_bSource.getAnalogTriggerForRouting(),
|
||||
reverseDirection, index.asIntBuffer());
|
||||
m_index = index.asIntBuffer().get(0);
|
||||
m_counter = null;
|
||||
setMaxPeriod(.5);
|
||||
break;
|
||||
case k2X:
|
||||
case k1X:
|
||||
m_encodingScale = m_encodingType == EncodingType.k1X ? 1 : 2;
|
||||
m_counter = new Counter(m_encodingType, m_aSource, m_bSource, reverseDirection);
|
||||
m_index = m_counter.getFPGAIndex();
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Illegal encoding type: " + m_encodingType);
|
||||
}
|
||||
m_distancePerPulse = 1.0;
|
||||
private void initEncoder(boolean reverseDirection, final EncodingType type) {
|
||||
m_encoder = EncoderJNI.initializeEncoder(m_aSource.getModuleForRouting(),
|
||||
(byte)m_aSource.getChannelForRouting(), m_aSource.getAnalogTriggerForRouting(),
|
||||
m_bSource.getModuleForRouting(), (byte)m_bSource.getChannelForRouting(),
|
||||
m_bSource.getAnalogTriggerForRouting(), reverseDirection, type.value);
|
||||
|
||||
m_pidSource = PIDSourceType.kDisplacement;
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_Encoder, m_index, m_encodingType.value);
|
||||
UsageReporting.report(tResourceType.kResourceType_Encoder, getFPGAIndex(), type.value);
|
||||
LiveWindow.addSensor("Encoder", m_aSource.getChannelForRouting(), this);
|
||||
}
|
||||
|
||||
@@ -124,7 +99,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
m_allocatedI = false;
|
||||
m_aSource = new DigitalInput(channelA);
|
||||
m_bSource = new DigitalInput(channelB);
|
||||
initEncoder(reverseDirection);
|
||||
initEncoder(reverseDirection, EncodingType.k4X);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,10 +138,9 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
if (encodingType == null) {
|
||||
throw new NullPointerException("Given encoding type was null");
|
||||
}
|
||||
m_encodingType = encodingType;
|
||||
m_aSource = new DigitalInput(channelA);
|
||||
m_bSource = new DigitalInput(channelB);
|
||||
initEncoder(reverseDirection);
|
||||
initEncoder(reverseDirection, encodingType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +163,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
m_aSource = new DigitalInput(channelA);
|
||||
m_bSource = new DigitalInput(channelB);
|
||||
m_indexSource = new DigitalInput(indexChannel);
|
||||
initEncoder(reverseDirection);
|
||||
initEncoder(reverseDirection, EncodingType.k4X);
|
||||
setIndexSource(indexChannel);
|
||||
}
|
||||
|
||||
@@ -231,7 +205,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
throw new NullPointerException("Digital Source B was null");
|
||||
}
|
||||
m_bSource = sourceB;
|
||||
initEncoder(reverseDirection);
|
||||
initEncoder(reverseDirection, EncodingType.k4X);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,7 +248,6 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
if (encodingType == null) {
|
||||
throw new NullPointerException("Given encoding type was null");
|
||||
}
|
||||
m_encodingType = encodingType;
|
||||
if (sourceA == null) {
|
||||
throw new NullPointerException("Digital Source A was null");
|
||||
}
|
||||
@@ -284,7 +257,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
}
|
||||
m_aSource = sourceA;
|
||||
m_bSource = sourceB;
|
||||
initEncoder(reverseDirection);
|
||||
initEncoder(reverseDirection, encodingType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,7 +288,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
m_aSource = sourceA;
|
||||
m_bSource = sourceB;
|
||||
m_indexSource = indexSource;
|
||||
initEncoder(reverseDirection);
|
||||
initEncoder(reverseDirection, EncodingType.k4X);
|
||||
setIndexSource(indexSource);
|
||||
}
|
||||
|
||||
@@ -339,7 +312,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
*/
|
||||
@SuppressWarnings("AbbreviationAsWordInName")
|
||||
public int getFPGAIndex() {
|
||||
return m_index;
|
||||
return EncoderJNI.getEncoderFPGAIndex(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,7 +321,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @return The encoding scale factor 1x, 2x, or 4x, per the requested encoding type.
|
||||
*/
|
||||
public int getEncodingScale() {
|
||||
return m_encodingScale;
|
||||
return EncoderJNI.getEncoderEncodingScale(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,12 +344,8 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
m_aSource = null;
|
||||
m_bSource = null;
|
||||
m_indexSource = null;
|
||||
if (m_counter != null) {
|
||||
m_counter.free();
|
||||
m_counter = null;
|
||||
} else {
|
||||
EncoderJNI.freeEncoder(m_encoder);
|
||||
}
|
||||
EncoderJNI.freeEncoder(m_encoder);
|
||||
m_encoder = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,13 +355,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @return Current raw count from the encoder
|
||||
*/
|
||||
public int getRaw() {
|
||||
int value;
|
||||
if (m_counter != null) {
|
||||
value = m_counter.get();
|
||||
} else {
|
||||
value = EncoderJNI.getEncoder(m_encoder);
|
||||
}
|
||||
return value;
|
||||
return EncoderJNI.getEncoderRaw(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -402,18 +365,14 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @return Current count from the Encoder adjusted for the 1x, 2x, or 4x scale factor.
|
||||
*/
|
||||
public int get() {
|
||||
return (int) (getRaw() * decodingScaleFactor());
|
||||
return EncoderJNI.getEncoder(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the Encoder distance to zero. Resets the current count to zero on the encoder.
|
||||
*/
|
||||
public void reset() {
|
||||
if (m_counter != null) {
|
||||
m_counter.reset();
|
||||
} else {
|
||||
EncoderJNI.resetEncoder(m_encoder);
|
||||
}
|
||||
EncoderJNI.resetEncoder(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -428,13 +387,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
*/
|
||||
@Deprecated
|
||||
public double getPeriod() {
|
||||
double measuredPeriod;
|
||||
if (m_counter != null) {
|
||||
measuredPeriod = m_counter.getPeriod() / decodingScaleFactor();
|
||||
} else {
|
||||
measuredPeriod = EncoderJNI.getEncoderPeriod(m_encoder);
|
||||
}
|
||||
return measuredPeriod;
|
||||
return EncoderJNI.getEncoderPeriod(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -447,11 +400,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* the device stopped. This is expressed in seconds.
|
||||
*/
|
||||
public void setMaxPeriod(double maxPeriod) {
|
||||
if (m_counter != null) {
|
||||
m_counter.setMaxPeriod(maxPeriod * decodingScaleFactor());
|
||||
} else {
|
||||
EncoderJNI.setEncoderMaxPeriod(m_encoder, maxPeriod);
|
||||
}
|
||||
EncoderJNI.setEncoderMaxPeriod(m_encoder, maxPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -462,11 +411,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @return True if the encoder is considered stopped.
|
||||
*/
|
||||
public boolean getStopped() {
|
||||
if (m_counter != null) {
|
||||
return m_counter.getStopped();
|
||||
} else {
|
||||
return EncoderJNI.getEncoderStopped(m_encoder);
|
||||
}
|
||||
return EncoderJNI.getEncoderStopped(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -475,28 +420,14 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @return The last direction the encoder value changed.
|
||||
*/
|
||||
public boolean getDirection() {
|
||||
if (m_counter != null) {
|
||||
return m_counter.getDirection();
|
||||
} else {
|
||||
return EncoderJNI.getEncoderDirection(m_encoder);
|
||||
}
|
||||
return EncoderJNI.getEncoderDirection(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* The scale needed to convert a raw counter value into a number of encoder pulses.
|
||||
*/
|
||||
private double decodingScaleFactor() {
|
||||
switch (m_encodingType) {
|
||||
case k1X:
|
||||
return 1.0;
|
||||
case k2X:
|
||||
return 0.5;
|
||||
case k4X:
|
||||
return 0.25;
|
||||
default:
|
||||
// This is never reached, EncodingType enum limits values
|
||||
return 0.0;
|
||||
}
|
||||
return EncoderJNI.getEncoderDecodingScaleFactor(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -506,7 +437,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @return The distance driven since the last reset
|
||||
*/
|
||||
public double getDistance() {
|
||||
return getRaw() * decodingScaleFactor() * m_distancePerPulse;
|
||||
return EncoderJNI.getEncoderDistance(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -516,7 +447,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @return The current rate of the encoder.
|
||||
*/
|
||||
public double getRate() {
|
||||
return m_distancePerPulse / getPeriod();
|
||||
return EncoderJNI.getEncoderRate(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -526,7 +457,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* from setDistancePerPulse().
|
||||
*/
|
||||
public void setMinRate(double minRate) {
|
||||
setMaxPeriod(m_distancePerPulse / minRate);
|
||||
EncoderJNI.setEncoderMinRate(m_encoder, minRate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -539,7 +470,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @param distancePerPulse The scale factor that will be used to convert pulses to useful units.
|
||||
*/
|
||||
public void setDistancePerPulse(double distancePerPulse) {
|
||||
m_distancePerPulse = distancePerPulse;
|
||||
EncoderJNI.setEncoderDistancePerPulse(m_encoder, distancePerPulse);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -549,9 +480,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @param reverseDirection true if the encoder direction should be reversed
|
||||
*/
|
||||
public void setReverseDirection(boolean reverseDirection) {
|
||||
if (m_counter != null) {
|
||||
m_counter.setReverseDirection(reverseDirection);
|
||||
}
|
||||
EncoderJNI.setEncoderReverseDirection(m_encoder, reverseDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -562,17 +491,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @param samplesToAverage The number of samples to average from 1 to 127.
|
||||
*/
|
||||
public void setSamplesToAverage(int samplesToAverage) {
|
||||
switch (m_encodingType) {
|
||||
case k4X:
|
||||
EncoderJNI.setEncoderSamplesToAverage(m_encoder, samplesToAverage);
|
||||
break;
|
||||
case k1X:
|
||||
case k2X:
|
||||
m_counter.setSamplesToAverage(samplesToAverage);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Illegal encoding type: " + m_encodingType);
|
||||
}
|
||||
EncoderJNI.setEncoderSamplesToAverage(m_encoder, samplesToAverage);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -583,15 +502,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @return SamplesToAverage The number of samples being averaged (from 1 to 127)
|
||||
*/
|
||||
public int getSamplesToAverage() {
|
||||
switch (m_encodingType) {
|
||||
case k4X:
|
||||
return EncoderJNI.getEncoderSamplesToAverage(m_encoder);
|
||||
case k1X:
|
||||
case k2X:
|
||||
return m_counter.getSamplesToAverage();
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return EncoderJNI.getEncoderSamplesToAverage(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -653,12 +564,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @param type The state that will cause the encoder to reset
|
||||
*/
|
||||
public void setIndexSource(int channel, IndexingType type) {
|
||||
boolean activeHigh =
|
||||
(type == IndexingType.kResetWhileHigh) || (type == IndexingType.kResetOnRisingEdge);
|
||||
boolean edgeSensitive =
|
||||
(type == IndexingType.kResetOnFallingEdge) || (type == IndexingType.kResetOnRisingEdge);
|
||||
|
||||
EncoderJNI.setEncoderIndexSource(m_encoder, channel, false, activeHigh, edgeSensitive);
|
||||
EncoderJNI.setEncoderIndexSource(m_encoder, channel, false, type.value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -669,21 +575,16 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* @param type The state that will cause the encoder to reset
|
||||
*/
|
||||
public void setIndexSource(DigitalSource source, IndexingType type) {
|
||||
boolean activeHigh =
|
||||
(type == IndexingType.kResetWhileHigh) || (type == IndexingType.kResetOnRisingEdge);
|
||||
boolean edgeSensitive =
|
||||
(type == IndexingType.kResetOnFallingEdge) || (type == IndexingType.kResetOnRisingEdge);
|
||||
|
||||
EncoderJNI.setEncoderIndexSource(m_encoder, source.getChannelForRouting(),
|
||||
source.getAnalogTriggerForRouting(), activeHigh, edgeSensitive);
|
||||
EncoderJNI.setEncoderIndexSource(m_encoder, source.getChannelForRouting(),
|
||||
source.getAnalogTriggerForRouting(), type.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
switch (m_encodingType) {
|
||||
case k4X:
|
||||
switch (EncoderJNI.getEncoderEncodingType(m_encoder)) {
|
||||
case 2: // value of k4X
|
||||
return "Quadrature Encoder";
|
||||
default:
|
||||
return "Encoder";
|
||||
@@ -708,7 +609,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Speed", getRate());
|
||||
m_table.putNumber("Distance", getDistance());
|
||||
m_table.putNumber("Distance per Tick", m_distancePerPulse);
|
||||
m_table.putNumber("Distance per Tick", EncoderJNI.getEncoderDistancePerPulse(m_encoder));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,34 +10,57 @@ package edu.wpi.first.wpilibj.hal;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
public class EncoderJNI extends JNIWrapper {
|
||||
public static native long initializeEncoder(byte portAModule, int portAPin,
|
||||
|
||||
public static native int initializeEncoder(byte portAModule, int portAPin,
|
||||
boolean portAAnalogTrigger, byte portBModule,
|
||||
int portBPin, boolean portBAnalogTrigger,
|
||||
boolean reverseDirection, IntBuffer index);
|
||||
boolean reverseDirection, int encodingType);
|
||||
|
||||
public static native void freeEncoder(long encoderPointer);
|
||||
public static native void freeEncoder(int encoderHandle);
|
||||
|
||||
public static native void resetEncoder(long encoderPointer);
|
||||
public static native int getEncoder(int encoderHandle);
|
||||
|
||||
public static native int getEncoderRaw(int encoderHandle);
|
||||
|
||||
public static native int getEncodingScaleFactor(int encoderHandle);
|
||||
|
||||
public static native void resetEncoder(int encoderHandle);
|
||||
|
||||
public static native int getEncoder(long encoderPointer);
|
||||
public static native double getEncoderPeriod(int encoderHandle);
|
||||
|
||||
public static native double getEncoderPeriod(long encoderPointer);
|
||||
public static native void setEncoderMaxPeriod(int encoderHandle, double maxPeriod);
|
||||
|
||||
public static native void setEncoderMaxPeriod(long encoderPointer, double maxPeriod);
|
||||
public static native boolean getEncoderStopped(int encoderHandle);
|
||||
|
||||
public static native boolean getEncoderStopped(long encoderPointer);
|
||||
public static native boolean getEncoderDirection(int encoderHandle);
|
||||
|
||||
public static native double getEncoderDistance(int encoderHandle);
|
||||
|
||||
public static native double getEncoderRate(int encoderHandle);
|
||||
|
||||
public static native void setEncoderMinRate(int encoderHandle, double minRate);
|
||||
|
||||
public static native void setEncoderDistancePerPulse(int encoderHandle, double distancePerPulse);
|
||||
|
||||
public static native boolean getEncoderDirection(long encoderPointer);
|
||||
|
||||
public static native void setEncoderReverseDirection(long encoderPointer,
|
||||
public static native void setEncoderReverseDirection(int encoderHandle,
|
||||
boolean reverseDirection);
|
||||
|
||||
public static native void setEncoderSamplesToAverage(long encoderPointer,
|
||||
public static native void setEncoderSamplesToAverage(int encoderHandle,
|
||||
int samplesToAverage);
|
||||
|
||||
public static native int getEncoderSamplesToAverage(long encoderPointer);
|
||||
public static native int getEncoderSamplesToAverage(int encoderHandle);
|
||||
|
||||
public static native void setEncoderIndexSource(long digitalPort, int pin,
|
||||
boolean analogTrigger, boolean activeHigh,
|
||||
boolean edgeSensitive);
|
||||
public static native void setEncoderIndexSource(int encoderHandle, int pin,
|
||||
boolean analogTrigger, int indexingType);
|
||||
|
||||
@SuppressWarnings("AbbreviationAsWordInName")
|
||||
public static native int getEncoderFPGAIndex(int encoderHandle);
|
||||
|
||||
public static native int getEncoderEncodingScale(int encoderHandle);
|
||||
|
||||
public static native double getEncoderDecodingScaleFactor(int encoderHandle);
|
||||
|
||||
public static native double getEncoderDistancePerPulse(int encoderHandle);
|
||||
|
||||
public static native int getEncoderEncodingType(int encoderHandle);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user