Moves Encoders to Handles and Moves WPILib Encoders to HAL (#124)

This commit is contained in:
Thad House
2016-07-03 15:22:22 -07:00
committed by Peter Johnson
parent b45e0917ae
commit 36ac37db8c
20 changed files with 1409 additions and 598 deletions

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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"

View File

@@ -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"

View File

@@ -36,3 +36,7 @@ typedef HalHandle HalCounterHandle;
typedef HalHandle HalCompressorHandle;
typedef HalHandle HalSolenoidHandle;
typedef HalHandle HalFPGAEncoderHandle;
typedef HalHandle HalEncoderHandle;

View File

@@ -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;

View File

@@ -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();
}
}

View 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;
};
}

View 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);
}
}

View 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);
}

View File

@@ -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:

View File

@@ -38,6 +38,8 @@ enum class HalHandleEnum {
PWM = 9,
DigitalPWM = 10,
Counter = 11,
FPGAEncoder = 12,
Encoder = 13,
Compressor = 14,
Solenoid = 15
};

View 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();
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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";

View File

@@ -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;

View File

@@ -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"

View File

@@ -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));
}
}

View File

@@ -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);
}